summaryrefslogtreecommitdiff
path: root/Silicon
diff options
context:
space:
mode:
authorJiewen Yao <jiewen.yao@intel.com>2017-06-19 10:55:06 +0800
committerJiewen Yao <jiewen.yao@intel.com>2017-06-20 15:12:29 +0800
commit646b243c0e3ef49b98071ca2c3fec15299b4d72f (patch)
tree00d62812fcedd3d1bf49692b863bb48a826f3ab0 /Silicon
parentf98787b719524d7ba9f2cefac0e8c8b8698cb02c (diff)
downloadedk2-platforms-646b243c0e3ef49b98071ca2c3fec15299b4d72f.tar.xz
Add KabylakeSiliconPkg
reviewed-by: Jiewen Yao <jiewen.yao@intel.com> reviewed-by: Michael A Kubacki <michael.a.kubacki@intel.com> reviewed-by: Amy Chan <amy.chan@intel.com> reviewed-by: Rangasai V Chaganty <rangasai.v.chaganty@intel.com> reviewed-by: Chasel Chiu <chasel.chiu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Chasel Chiu <chasel.chiu@intel.com>
Diffstat (limited to 'Silicon')
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Contributions.txt218
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h101
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigFspData.h65
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h101
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuOverclockingConfig.h151
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h59
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h178
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h76
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h145
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtVrConfig.h104
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h122
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuAccess.h21
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuDataStruct.h194
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h29
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPowerMgmt.h106
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuRegs.h330
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuMailboxLib.h96
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h102
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLib.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLibPreMem.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuGlobalNvsArea.h167
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuInfo.h128
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuInitDataHob.h50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuPrivateData.h27
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/Library/CpuCommonLib.h192
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/PowerMgmtNvsStruct.h178
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.c95
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.inf29
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/CpuPrintPolicy.c286
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.c430
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.inf67
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLibrary.h35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/CpuPrintPolicy.c102
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLib.c143
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibPreMem.inf50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibrary.h40
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c466
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h34
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/CpuCommonLib.c562
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/PeiDxeSmmCpuCommonLib.inf49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/BootFirmwareMediaProtection.c399
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/DebugModeDisabled.c94
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HardwareRootedBootIntegrity.c30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.c387
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.h276
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.inf108
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/IntegratedDeviceDmaProtection.c150
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MeasuredBootEnforcement.c30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MpServiceHelp.c216
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureCpuConfiguration.c344
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureIntegratedGraphicsConfiguration.c221
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureMemoryMapConfiguration.c752
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecurePCHConfiguration.c299
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureSystemAgentConfiguration.c51
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SignedFirmwareUpdate.c30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/ConfigBlock.h59
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/HstiFeatureBit.h183
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Library/AslUpdateLib.h146
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Library/ConfigBlockLib.h70
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Library/MmPciLib.h34
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Library/PeiSiPolicyUpdateLib.h143
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiConfigBlockLib.h64
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiPolicyLib.h114
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiliconInitLib.h34
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/PcieRegs.h309
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiInitPpi.h22
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiPolicy.h36
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/Protocol/SiPolicyProtocol.h66
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Include/SiPolicyStruct.h110
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/Library/PcieInitLib.h839
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/SiConfigHob.h24
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconBuild.bat62
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPkg.dsc203
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPrivate.dec143
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c151
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c93
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf40
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c314
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.c131
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.inf37
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c37
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspCpuPolicyInitLib.c366
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMePolicyInitLib.c129
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMiscUpdInitLib.c56
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPchPolicyInitLib.c713
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.c141
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.h179
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.inf146
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSaPolicyInitLib.c578
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSiPolicyInitLib.c51
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.c47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.h24
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitLib.h37
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitPreMem.c48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiSiPolicyInit.h24
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c244
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf62
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibPreMem.c128
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c46
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInit.c215
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitLib.inf57
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitPreMem.c240
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/License.txt25
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Me/Include/ConfigBlock/MePeiConfig.h135
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Me/Include/Library/PeiMePolicyLib.h92
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Me/Include/MeChipset.h48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Me/Include/MePolicyCommon.h31
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.c261
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.inf52
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLibrary.h28
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h791
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl849
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl230
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl616
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl1156
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf40
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl213
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl240
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl214
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl186
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl154
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl247
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl749
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl310
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl558
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl144
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl70
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h53
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h53
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h41
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h180
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h45
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h76
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h71
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h63
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h67
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h39
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h60
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h435
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h215
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h34
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h193
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h56
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h56
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h38
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h176
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h233
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h38
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h338
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h248
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h207
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h707
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h225
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h37
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h345
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h102
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h64
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h114
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h260
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h160
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h110
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h196
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h113
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h170
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h162
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h219
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h98
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h28
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h113
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h27
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h104
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h71
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h101
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h65
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h62
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h28
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h98
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h33
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h141
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h74
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h151
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h115
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h57
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h137
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h121
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h139
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h157
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h126
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h299
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h118
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h151
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h214
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h123
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h529
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h201
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h185
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h74
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h94
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h148
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h610
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h138
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h524
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h111
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h652
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h364
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h720
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h202
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h325
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h149
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h309
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h107
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h140
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h490
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h128
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h212
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h290
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h62
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h191
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h284
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h401
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h166
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h401
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h91
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h298
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h129
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h33
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h243
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c161
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf46
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c996
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf46
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c325
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf56
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c367
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf58
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c505
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c2691
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h327
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c685
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c190
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf51
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c1137
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c146
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c928
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c514
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c334
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c338
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c268
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c458
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c136
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c448
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c385
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c527
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf45
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c225
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c138
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c41
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c311
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c783
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c223
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c80
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c892
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf93
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c306
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c194
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c286
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf58
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf59
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c202
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c60
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c1058
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf51
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c318
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c842
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c336
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c545
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c305
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c318
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c200
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c519
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c127
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c1933
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h45
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf52
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c1169
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c652
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c216
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c465
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c57
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c247
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c504
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h320
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c699
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf101
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf80
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c169
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c286
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c125
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c1869
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c112
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c130
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c308
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h344
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf107
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c415
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c464
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c160
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c74
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c73
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c913
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h193
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c2497
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf113
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h949
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c952
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c1385
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h337
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c333
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h162
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c702
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c96
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c169
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c235
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c232
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c790
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h114
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c400
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h148
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c254
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/Include/Library/SecPlatformLib.h88
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Guid/SmramMemoryReserve.h60
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/DataHub.h222
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/Legacy8259.h297
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyBios.h1523
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyInterrupt.h128
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelGraphicsPeimVbt/PeiVbt.binbin0 -> 4608 bytes
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/AcpiS3Context.h73
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/ConsoleOutDevice.h23
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/MemoryTypeInformation.h36
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Library/ResetSystemLib.h68
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmAccess.h145
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmControl.h96
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Protocol/SmmVariable.h39
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SampleCode/Pch/AcpiTables/Dsdt/PchSmb.asl543
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SiPkg.dec628
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SiPkgBuildOption.dsc119
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SiPkgCommonLib.dsc73
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SiPkgDxe.dsc73
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SiPkgDxeLib.dsc47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SiPkgPei.dsc28
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SiPkgPeiLib.dsc54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.aslc411
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.h30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/HostBus.asl733
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaAcpiTables.inf61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Igfx.asl1782
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxCommon.asl487
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxDsm.asl359
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpGbda.asl119
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpRn.asl297
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpSbcb.asl268
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl135
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl28
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf60
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsDxeConfig.h57
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsPeiConfig.h36
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryConfig.h533
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MiscDxeConfig.h35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h38
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/VtdConfig.h46
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/DmaRemappingTable.h112
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h65
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h91
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h34
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/MemInfoHob.h244
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/GopPolicy.h78
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/IgdOpRegion.h170
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/MemInfo.h122
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaGlobalNvsArea.h32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaNvs.h138
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h58
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaAccess.h52
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaPolicyCommon.h40
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaRegs.h787
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h107
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c250
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h26
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h27
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.S58
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.asm85
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.nasm79
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.c747
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.h313
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.c365
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.inf72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibSample.c281
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibrary.h44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/SaPrintPolicy.c326
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcCommonTypes.h235
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcInterface.h1756
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcRmtData.h237
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcSpdData.h1173
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcTypes.h237
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.c73
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.h46
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.c525
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.h189
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c304
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h33
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h102
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf109
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.c931
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.h61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccess.inf55
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.c434
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.h171
481 files changed, 108474 insertions, 0 deletions
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Contributions.txt b/Silicon/Intel/KabylakeSiliconPkg/Contributions.txt
new file mode 100644
index 0000000000..f87cbd73c6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Contributions.txt
@@ -0,0 +1,218 @@
+
+======================
+= Code Contributions =
+======================
+
+To make a contribution to a TianoCore project, follow these steps.
+1. Create a change description in the format specified below to
+ use in the source control commit log.
+2. Your commit message must include your "Signed-off-by" signature,
+ and "Contributed-under" message.
+3. Your "Contributed-under" message explicitly states that the
+ contribution is made under the terms of the specified
+ contribution agreement. Your "Contributed-under" message
+ must include the name of contribution agreement and version.
+ For example: Contributed-under: TianoCore Contribution Agreement 1.0
+ The "TianoCore Contribution Agreement" is included below in
+ this document.
+4. Submit your code to the TianoCore project using the process
+ that the project documents on its web page. If the process is
+ not documented, then submit the code on development email list
+ for the project.
+5. It is preferred that contributions are submitted using the same
+ copyright license as the base project. When that is not possible,
+ then contributions using the following licenses can be accepted:
+ * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause
+ * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause
+ * MIT: http://opensource.org/licenses/MIT
+ * Python-2.0: http://opensource.org/licenses/Python-2.0
+ * Zlib: http://opensource.org/licenses/Zlib
+
+ Contributions of code put into the public domain can also be
+ accepted.
+
+ Contributions using other licenses might be accepted, but further
+ review will be required.
+
+=====================================================
+= Change Description / Commit Message / Patch Email =
+=====================================================
+
+Your change description should use the standard format for a
+commit message, and must include your "Signed-off-by" signature
+and the "Contributed-under" message.
+
+== Sample Change Description / Commit Message =
+
+=== Start of sample patch email message ===
+
+From: Contributor Name <contributor@example.com>
+Subject: [PATCH] CodeModule: Brief-single-line-summary
+
+Full-commit-message
+
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Contributor Name <contributor@example.com>
+---
+
+An extra message for the patch email which will not be considered part
+of the commit message can be added here.
+
+Patch content inline or attached
+
+=== End of sample patch email message ===
+
+=== Notes for sample patch email ===
+
+* The first line of commit message is taken from the email's subject
+ line following [PATCH]. The remaining portion of the commit message
+ is the email's content until the '---' line.
+* git format-patch is one way to create this format
+
+=== Definitions for sample patch email ===
+
+* "CodeModule" is a short idenfier for the affected code. For
+ example MdePkg, or MdeModulePkg UsbBusDxe.
+* "Brief-single-line-summary" is a short summary of the change.
+* The entire first line should be less than ~70 characters.
+* "Full-commit-message" a verbose multiple line comment describing
+ the change. Each line should be less than ~70 characters.
+* "Contributed-under" explicitely states that the contribution is
+ made under the terms of the contribtion agreement. This
+ agreement is included below in this document.
+* "Signed-off-by" is the contributor's signature identifying them
+ by their real/legal name and their email address.
+
+========================================
+= TianoCore Contribution Agreement 1.0 =
+========================================
+
+INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION,
+INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE
+PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE
+TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE
+TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR
+REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE
+CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED
+BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS
+AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE
+AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT
+USE THE CONTENT.
+
+Unless otherwise indicated, all Content made available on the TianoCore
+site is provided to you under the terms and conditions of the BSD
+License ("BSD"). A copy of the BSD License is available at
+http://opensource.org/licenses/bsd-license.php
+or when applicable, in the associated License.txt file.
+
+Certain other content may be made available under other licenses as
+indicated in or with such Content. (For example, in a License.txt file.)
+
+You accept and agree to the following terms and conditions for Your
+present and future Contributions submitted to TianoCore site. Except
+for the license granted to Intel hereunder, You reserve all right,
+title, and interest in and to Your Contributions.
+
+== SECTION 1: Definitions ==
+* "You" or "Contributor" shall mean the copyright owner or legal
+ entity authorized by the copyright owner that is making a
+ Contribution hereunder. All other entities that control, are
+ controlled by, or are under common control with that entity are
+ considered to be a single Contributor. For the purposes of this
+ definition, "control" means (i) the power, direct or indirect, to
+ cause the direction or management of such entity, whether by
+ contract or otherwise, or (ii) ownership of fifty percent (50%)
+ or more of the outstanding shares, or (iii) beneficial ownership
+ of such entity.
+* "Contribution" shall mean any original work of authorship,
+ including any modifications or additions to an existing work,
+ that is intentionally submitted by You to the TinaoCore site for
+ inclusion in, or documentation of, any of the Content. For the
+ purposes of this definition, "submitted" means any form of
+ electronic, verbal, or written communication sent to the
+ TianoCore site or its representatives, including but not limited
+ to communication on electronic mailing lists, source code
+ control systems, and issue tracking systems that are managed by,
+ or on behalf of, the TianoCore site for the purpose of
+ discussing and improving the Content, but excluding
+ communication that is conspicuously marked or otherwise
+ designated in writing by You as "Not a Contribution."
+
+== SECTION 2: License for Contributions ==
+* Contributor hereby agrees that redistribution and use of the
+ Contribution in source and binary forms, with or without
+ modification, are permitted provided that the following
+ conditions are met:
+** Redistributions of source code must retain the Contributor's
+ copyright notice, this list of conditions and the following
+ disclaimer.
+** Redistributions in binary form must reproduce the Contributor's
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+* Disclaimer. None of the names of Contributor, Intel, or the names
+ of their respective contributors may be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+* Contributor grants a license (with the right to sublicense) under
+ claims of Contributor's patents that Contributor can license that
+ are infringed by the Contribution (as delivered by Contributor) to
+ make, use, distribute, sell, offer for sale, and import the
+ Contribution and derivative works thereof solely to the minimum
+ extent necessary for licensee to exercise the granted copyright
+ license; this patent license applies solely to those portions of
+ the Contribution that are unmodified. No hardware per se is
+ licensed.
+* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE
+ CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+ CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+
+== SECTION 3: Representations ==
+* You represent that You are legally entitled to grant the above
+ license. If your employer(s) has rights to intellectual property
+ that You create that includes Your Contributions, You represent
+ that You have received permission to make Contributions on behalf
+ of that employer, that Your employer has waived such rights for
+ Your Contributions.
+* You represent that each of Your Contributions is Your original
+ creation (see Section 4 for submissions on behalf of others).
+ You represent that Your Contribution submissions include complete
+ details of any third-party license or other restriction
+ (including, but not limited to, related patents and trademarks)
+ of which You are personally aware and which are associated with
+ any part of Your Contributions.
+
+== SECTION 4: Third Party Contributions ==
+* Should You wish to submit work that is not Your original creation,
+ You may submit it to TianoCore site separately from any
+ Contribution, identifying the complete details of its source
+ and of any license or other restriction (including, but not
+ limited to, related patents, trademarks, and license agreements)
+ of which You are personally aware, and conspicuously marking the
+ work as "Submitted on behalf of a third-party: [named here]".
+
+== SECTION 5: Miscellaneous ==
+* Applicable Laws. Any claims arising under or relating to this
+ Agreement shall be governed by the internal substantive laws of
+ the State of Delaware or federal courts located in Delaware,
+ without regard to principles of conflict of laws.
+* Language. This Agreement is in the English language only, which
+ language shall be controlling in all respects, and all versions
+ of this Agreement in any other language shall be for accommodation
+ only and shall not be binding. All communications and notices made
+ or given pursuant to this Agreement, and all documentation and
+ support to be provided, unless otherwise noted, shall be in the
+ English language.
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h
new file mode 100644
index 0000000000..863a4fcdf8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h
@@ -0,0 +1,101 @@
+/** @file
+ CPU Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_CONFIG_H_
+#define _CPU_CONFIG_H_
+
+#include <ConfigBlock/CpuConfigFspData.h>
+#define CPU_CONFIG_REVISION 3
+
+
+extern EFI_GUID gCpuConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Configuration Structure.
+ This structure is identical to CPU_CONFIG_FSP.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add SkipMpInit : Silicon Initialization will skip MP Initialization for FSP only
+ <b>Revision 3</b>:
+ - Deprecated and moved FclkFrequency, VmxEnable to CPU_CONFIG_LIB_PREMEM_CONFIG
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Enable or Disable Advanced Encryption Standard (AES) feature.
+ For some countries, this should be disabled for legal reasons.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 AesEnable : 1;
+ /**
+ @deprecated since revision 3. Moved to CPU_CONFIG_LIB_PREMEM_CONFIG
+ Processor Early Power On Configuration FCLK setting.
+ - <b>0: 800 MHz (ULT/ULX)</b>.
+ - <b>1: 1 GHz (DT/Halo)</b>. Not supported on ULT/ULX.
+ - 2: 400 MHz.
+ - 3: Reserved.
+ **/
+ UINT32 FClkFrequency : 2;
+ UINT32 EnableRsr : 1; ///< Enable or Disable RSR feature; 0: Disable; <b>1: Enable </b>
+ /**
+ Policies to obtain CPU temperature.
+ - <b>0: ACPI thermal management uses EC reported temperature values</b>.
+ - 1: ACPI thermal management uses DTS SMM mechanism to obtain CPU temperature values.
+ - 2: ACPI Thermal Management uses EC reported temperature values and DTS SMM is used to handle Out of Spec condition.
+ **/
+ UINT32 EnableDts : 2;
+ UINT32 SmmbaseSwSmiNumber : 8; ///< Software SMI number for handler to save CPU information in SMRAM.
+ /**
+ @deprecated since revision 3. Moved to CPU_CONFIG_LIB_PREMEM_CONFIG
+ Enable or Disable Virtual Machine Extensions (VMX) feature.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 VmxEnable : 1;
+ /**
+ Enable or Disable Trusted Execution Technology (TXT) feature.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 TxtEnable : 1;
+ UINT32 SkipMpInit : 1; ///< For Fsp only, Silicon Initialization will skip MP Initialization (including BSP) if enabled. For non-FSP, this should always be 0.
+ UINT32 RsvdBits : 15; ///< Reserved for future use
+ EFI_PHYSICAL_ADDRESS MicrocodePatchAddress; ///< Pointer to microcode patch that is suitable for this processor.
+} CPU_CONFIG;
+
+/**
+ FSP CPU Configuration Structure.
+ This structure is identical to CPU_CONFIG.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 Data; ///< Config Block Data
+ EFI_PHYSICAL_ADDRESS MicrocodePatchAddress; ///< Pointer to microcode patch that is suitable for this processor.
+} CPU_CONFIG_FSP;
+
+typedef union {
+ CPU_CONFIG CpuConfig;
+ CPU_CONFIG_FSP CpuConfigFsp;
+} CPU_CONFIG_UNION;
+
+#pragma pack (pop)
+
+#endif // _CPU_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigFspData.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigFspData.h
new file mode 100644
index 0000000000..8f333cffeb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigFspData.h
@@ -0,0 +1,65 @@
+/** @file
+ FSP CPU Data Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_CONFIG_FSP_DATA_H_
+#define _CPU_CONFIG_FSP_DATA_H_
+
+#pragma pack (push,1)
+typedef union {
+ struct {
+ /**
+ Enable or Disable Advanced Encryption Standard (AES) feature.
+ For some countries, this should be disabled for legal reasons.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 AesEnable : 1;
+ /**
+ Processor Early Power On Configuration FCLK setting.
+ - <b>0: 800 MHz (ULT/ULX)</b>.
+ - <b>1: 1 GHz (DT/Halo)</b>. Not supported on ULT/ULX.
+ - 2: 400 MHz.
+ - 3: Reserved.
+ **/
+ UINT32 FClkFrequency : 2;
+ UINT32 EnableRsr : 1; ///< Enable or Disable RSR feature; 0: Disable; <b>1: Enable </b>
+ /**
+ Policies to obtain CPU temperature.
+ - <b>0: ACPI thermal management uses EC reported temperature values</b>.
+ - 1: ACPI thermal management uses DTS SMM mechanism to obtain CPU temperature values.
+ - 2: ACPI Thermal Management uses EC reported temperature values and DTS SMM is used to handle Out of Spec condition.
+ **/
+ UINT32 EnableDts : 2;
+ UINT32 SmmbaseSwSmiNumber : 8; ///< Software SMI number for handler to save CPU information in SMRAM.
+ /**
+ Enable or Disable Virtual Machine Extensions (VMX) feature.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 VmxEnable : 1;
+ /**
+ Enable or Disable Trusted Execution Technology (TXT) feature.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 TxtEnable : 1;
+ UINT32 SkipMpInit : 1; ///< For Fsp only, Silicon Initialization will skip MP Initialization (including BSP) if enabled. For non-FSP, this should always be 0.
+ UINT32 RsvdBits : 15; ///< Reserved for future use
+ UINT32 Reserved;
+ } Bits;
+ UINT32 Uint32[2];
+ } CPU_CONFIG_FSP_DATA;
+
+#pragma pack (pop)
+
+#endif // _CPU_CONFIG_FSP_DATA_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h
new file mode 100644
index 0000000000..19e41287ce
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h
@@ -0,0 +1,101 @@
+/** @file
+ CPU PreMemory Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
+#define _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
+
+#define CPU_CONFIG_LIB_PREMEM_CONFIG_REVISION 2
+
+extern EFI_GUID gCpuConfigLibPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Config Library PreMemory Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+
+ <b>Revision 2</b>:
+ - Added PeciC10Reset.
+ - Added PeciSxReset.
+
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 HyperThreading : 1; ///< Enable or Disable Hyper Threading; 0: Disable; <b>1: Enable</b>.
+ /**
+ Enable or disable override of default max non-turbo ratio. If enabled, BIOS will take the value specified in
+ CpuRatio policy and updates the max non-turbo ratio. See policy CpuRatio for more details.
+ If disabled, BIOS will use the default max non-turbo ratio, and will not use any flex ratio setting.
+ - <b>0: Disable</b>
+ - 1: Enable
+ **/
+ UINT32 CpuRatioOverride : 1;
+ /**
+ Sets the boot frequency starting from reset vector.
+ - 0: Maximum battery performance.
+ - <b>1: Maximum non-turbo performance</b>.
+ - 2: Turbo performance.
+ @note If Turbo is selected BIOS will start in max non-turbo mode and switch to Turbo mode.
+ **/
+ UINT32 BootFrequency : 2;
+ /**
+ Number of processor cores to enable.
+ - <b> 0: All cores</b>
+ - 1: 1 core
+ - 2: 2 cores
+ - 3: 3 cores
+ **/
+ UINT32 ActiveCoreCount : 3;
+ /**
+ Processor Early Power On Configuration FCLK setting.
+ - <b>0: 800 MHz (ULT/ULX)</b>.
+ - <b>1: 1 GHz (DT/Halo)</b>. Not supported on ULT/ULX.
+ - 2: 400 MHz.
+ - 3: Reserved.
+ **/
+ UINT32 FClkFrequency : 2;
+ UINT32 JtagC10PowerGateDisable : 1; ///< Power JTAG in C10 and deeper power states; <b>0: Disable</b>; 1: Enable.
+ UINT32 BistOnReset : 1; ///< <b>(Test)</b> Enable or Disable BIST on Reset; <b>0: Disable</b>; 1: Enable.
+ /**
+ Enable or Disable Virtual Machine Extensions (VMX) feature.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 VmxEnable : 1;
+ /**
+ Enables a mailbox command to resolve rare PECI related Sx issues.
+ @note This should only be used on systems that observe PECI Sx issues.
+ - <b>0: Disable</b>
+ - 1: Enable
+ **/
+ UINT32 PeciSxReset : 1;
+ /**
+ Enables a mailbox command to resolve rare PECI related C10 issues.
+ @note This should only be used on systems that observe PECI C10 issues.
+ - <b>0: Disable</b>
+ - 1: Enable
+ **/
+ UINT32 PeciC10Reset : 1;
+ UINT32 RsvdBits : 18;
+ /**
+ CpuRatio - When CpuRatioOverride is enabled, max non-turbo ratio (Flexible Ratio Boot) is set to CpuRatio.
+ **/
+ UINT8 CpuRatio;
+ UINT8 Reserved[3]; ///< Reserved for alignment
+} CPU_CONFIG_LIB_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuOverclockingConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuOverclockingConfig.h
new file mode 100644
index 0000000000..735e79c491
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuOverclockingConfig.h
@@ -0,0 +1,151 @@
+/** @file
+ CPU Overclocking Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_OVERCLOCKING_PREMEM_CONFIG_H_
+#define _CPU_OVERCLOCKING_PREMEM_CONFIG_H_
+
+#define CPU_OVERCLOCKING_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuOverclockingPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Overclocking Premem Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Overclocking support. This controls whether OC mailbox transactions are sent.
+ If disabled, all policies in this config block besides OcSupport and OcLock will be ignored.
+ <b>0: Disable</b>;
+ 1: Enable.
+ @note If PcdOverclockEnable is disabled, this should also be disabled.
+ **/
+ UINT32 OcSupport : 1;
+ UINT32 OcLock : 1; ///< If enabled, sets OC lock bit in MSR 0x194[20], locking the OC mailbox and other OC configuration settings.; <b>0: Disable</b>; 1: Enable (Lock).
+ /**
+ Core voltage mode, specifies which voltage mode the processor will be operating.
+ <b>0: Adaptive Mode</b> allows the processor to interpolate a voltage curve when beyond fused P0 range;
+ 1: Override, sets one voltage for for the entire frequency range, Pn-P0.
+ **/
+ UINT32 CoreVoltageMode : 1;
+ UINT32 CorePllVoltageOffset : 6; ///< Core PLL voltage offset. <b>0: No offset</b>. Range 0-63 in 17.5mv units.
+ UINT32 Avx2RatioOffset : 5; ///< AVX2 Ratio Offset. <b>0: No offset</b>. Range is 0-31. Used to lower the AVX ratio to maximize possible ratio for SSE workload.
+ UINT32 Avx3RatioOffset : 5; ///< AVX3 Ratio Offset. <b>0: No offset</b>. Range is 0-31. Used to lower the AVX3 ratio to maximize possible ratio for SSE workload.
+ UINT32 BclkAdaptiveVoltage : 1; ///< Bclk Adaptive Voltage enable/disable. <b>0: Disabled</b>, 1: Enabled. When enabled, the CPU V/F curves are aware of BCLK frequency when calculated.
+ /**
+ Ring Downbin enable/disable.
+ When enabled, the CPU will force the ring ratio to be lower than the core ratio.
+ Disabling will allow the ring and core ratios to run at the same frequency.
+ Uses OC Mailbox command 0x19.
+ <b>0: Disables Ring Downbin feature</b>. 1: Enables Ring downbin feature.
+ **/
+ UINT32 RingDownBin : 1;
+ UINT32 RsvdBits : 11; ///< Reserved for future use
+ /**
+ Maximum core turbo ratio override allows to increase CPU core frequency beyond the fused max turbo ratio limit (P0).
+ <b>0. no override/HW defaults.</b>. Range 0-83.
+ **/
+ UINT16 CoreMaxOcRatio;
+ /**
+ The core voltage override which is applied to the entire range of cpu core frequencies.
+ Used when CoreVoltageMode = Override.
+ <b>0. no override</b>. Range 0-2000 mV.
+ **/
+ UINT16 CoreVoltageOverride;
+ /**
+ Adaptive Turbo voltage target used to define the interpolation voltage point when the cpu is operating in turbo mode range.
+ Used when CoreVoltageMode = Adaptive.
+ <b>0. no override</b>. Range 0-2000mV.
+ **/
+ UINT16 CoreVoltageAdaptive;
+ /**
+ The core voltage offset applied on top of all other voltage modes. This offset is applied over the entire frequency range.
+ This is a 2's complement number in mV units. <b>Default: 0</b> Range: -1000 to 1000.
+ **/
+ INT16 CoreVoltageOffset;
+ UINT8 RingMaxOcRatio; ///< Maximum ring ratio override allows to increase CPU ring frequency beyond the fused max turbo ratio limit. <b>0: Hardware defaults.</b> Range: 0-83.
+ UINT8 RingMinOcRatio; ///< Minimum ring ratio override. <b>0: Hardware defaults.</b> Range: 0-83.
+ UINT32 GtPllVoltageOffset : 6; ///< GT PLL voltage offset. <b>0: No offset</b>. Range 0-63 in 17.5mv units.
+ UINT32 RingPllVoltageOffset : 6; ///< Ring PLL voltage offset. <b>0: No offset</b>. Range 0-63 in 17.5mv units.
+ UINT32 SaPllVoltageOffset : 6; ///< System Agent PLL voltage offset. <b>0: No offset</b>. Range 0-63 in 17.5mv units.
+ UINT32 McPllVoltageOffset : 6; ///< Memory Controller PLL voltage offset. <b>0: No offset</b>. Range 0-63 in 17.5mv units.
+ UINT32 RsvdBits1 : 8;
+ UINT8 Rsvd[2]; ///< Reserved for future use & Config block alignment
+} CPU_OVERCLOCKING_PREMEM_CONFIG;
+
+/**
+ @deprecated CPU_OVERCLOCKING_CONFIG since revision 2.
+ This structure is not used, use CPU_OVERCLOCKING_PREMEM_CONFIG instead
+
+ CPU Overclocking Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+
+ <b>Revision 2</b>:
+ - Deprecated CPU_OVERCLOCKING_CONFIG
+
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 OcSupport : 1; ///< @deprecated since revision 2. Overclocking support. This controls whether OC mailbox transactions are sent. <b>0: Disable</b>; 1: Enable.
+ UINT32 OcLock : 1; ///< @deprecated since revision 2. If enabled, sets OC lock bit in MSR 0x194[20], locking the OC mailbox and other OC configuration settings.; <b>0: Disable</b>; 1: Enable (Lock).
+ /**
+ Core voltage mode, specifies which voltage mode the processor will be operating.
+ <b>0: Adaptive Mode</b> allows the processor to interpolate a voltage curve when beyond fused P0 range;
+ 1: Override, sets one voltage for for the entire frequency range, Pn-P0.
+ **/
+ UINT32 CoreVoltageMode : 1;
+ UINT32 CorePllVoltageOffset : 6; ///< @deprecated since revision 2. Core PLL voltage offset. <b>0: No offset</b>. Range 0-63 in 15mv units.
+ UINT32 Avx2RatioOffset : 5; ///< @deprecated since revision 2. AVX2 Ratio Offset. <b>0: No offset</b>. Range is 0-31. Used to lower the AVX ratio to maximize possible ratio for SSE workload.
+ UINT32 BclkAdaptiveVoltage : 1; ///< @deprecated since revision 2. Bclk Adaptive Voltage enable/disable. <b>0: Disabled</b>, 1: Enabled. When enabled, the CPU V/F curves are aware of BCLK frequency when calculated.
+ UINT32 RsvdBits : 17; ///< Reserved for future use
+ /**
+ @deprecated since revision 2.
+ Maximum core turbo ratio override allows to increase CPU core frequency beyond the fused max turbo ratio limit (P0).
+ <b>0. no override/HW defaults.</b>. Range 0-83.
+ **/
+ UINT16 CoreMaxOcRatio;
+ /**
+ @deprecated since revision 2.
+ The core voltage override which is applied to the entire range of cpu core frequencies.
+ Used when CoreVoltageMode = Override.
+ <b>0. no override</b>. Range 0-2000 mV.
+ **/
+ UINT16 CoreVoltageOverride;
+ /**
+ @deprecated since revision 2.
+ Adaptive Turbo voltage target used to define the interpolation voltage point when the cpu is operating in turbo mode range.
+ Used when CoreVoltageMode = Adaptive.
+ <b>0. no override</b>. Range 0-2000mV.
+ **/
+ UINT16 CoreVoltageAdaptive;
+ /**
+ @deprecated since revision 2.
+ The core voltage offset applied on top of all other voltage modes. This offset is applied over the entire frequency range.
+ This is a 2's complement number in mV units. <b>Default: 0</b> Range: -1000 to 1000.
+ **/
+ INT16 CoreVoltageOffset;
+ UINT8 RingMaxOcRatio; ///< @deprecated since revision 2. Maximum ring ratio override allows to increase CPU ring frequency beyond the fused max turbo ratio limit. <b>0: Hardware defaults.</b> Range: 0-83.
+ UINT8 RingMinOcRatio; ///< @deprecated since revision 2. Minimum clr turbo ratio override. <b>0: Hardware defaults.</b> Range: 0-83.
+ UINT8 Rsvd[2]; ///< Reserved for future use & Config block alignment
+} CPU_OVERCLOCKING_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_OVERCLOCKING_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h
new file mode 100644
index 0000000000..d8b5a2ed98
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h
@@ -0,0 +1,59 @@
+/** @file
+ CPU PID Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_PID_TEST_CONFIG_H_
+#define _CPU_PID_TEST_CONFIG_H_
+
+#define CPU_PID_TEST_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuPidTestConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ PID Tuning Configuration Structure.
+ Domain is mapped to Kp = 0, Ki = 1, Kd = 2.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT16 Ratl[3]; ///< RATL setting, in 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr0[3]; ///< VR Thermal Design Current for VR0. In 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr1[3]; ///< VR Thermal Design Current for VR1. In 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr2[3]; ///< VR Thermal Design Current for VR2. In 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr3[3]; ///< VR Thermal Design Current for VR3. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl1Msr[3]; ///< Power Budget Management Psys PL1 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl1MmioPcs[3]; ///< Power Budget Management Psys PL1 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl2Msr[3]; ///< Power Budget Management Psys PL2 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl2MmioPcs[3]; ///< Power Budget Management Psys PL2 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl1Msr[3]; ///< Power Budget Management Package PL1 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl1MmioPcs[3]; ///< Power Budget Management Package PL1 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl2Msr[3]; ///< Power Budget Management Package PL2 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl2MmioPcs[3]; ///< Power Budget Management Package PL2 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl1Msr[3]; ///< DDR PL1 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl1MmioPcs[3]; ///< DDR PL1 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl2Msr[3]; ///< DDR PL2 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl2MmioPcs[3]; ///< DDR PL2 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ /**
+ Enable or Disable PID Tuning programming flow.
+ If disabled, all other policies in this config block are ignored.
+ **/
+ UINT8 PidTuning;
+ UINT8 Rsvd; ///< Reserved for DWORD alignment.
+} CPU_PID_TEST_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_PID_TEST_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h
new file mode 100644
index 0000000000..68dc9195ae
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h
@@ -0,0 +1,178 @@
+/** @file
+ CPU Power Management Basic Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_POWER_MGMT_BASIC_CONFIG_H_
+#define _CPU_POWER_MGMT_BASIC_CONFIG_H_
+
+#define CPU_POWER_MGMT_BASIC_CONFIG_REVISION 2
+
+extern EFI_GUID gCpuPowerMgmtBasicConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Power Management Basic Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Deprecated S3RestoreMsrSwSmiNumber.
+ Replace SW SMI number to restore the power mgmt MSRs with CpuPowerMgmtLib during S3 resume.
+ <b>Revision 3</b>:
+ - Added FiveCoreRatioLimit, SixCoreRatioLimit, SevenCoreRatioLimit, EightCoreRatioLimit for 6 and 8 core support.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Sets the boot frequency starting from reset vector.
+ - 0: Maximum battery performance.
+ - <b>1: Maximum non-turbo performance</b>.
+ - 2: Turbo performance.
+ @note If Turbo is selected BIOS will start in max non-turbo mode and switch to Turbo mode.
+ **/
+ UINT32 BootFrequency : 2;
+ UINT32 SkipSetBootPState : 1; ///< Choose whether to skip SetBootPState function for all APs; <b>0: Do not skip</b>; 1: Skip.
+ /**
+ Enable or Disable Intel Speed Shift Technology.
+ Enabling allows for processor control of P-state transitions.
+ 0: Disable; <b>1: Enable;</b> Bit 1 is ignored.
+ @note Currently this feature is recommended to be enabled only on win10
+ **/
+ UINT32 Hwp : 2;
+ /**
+ Hardware Duty Cycle Control configuration. 0: Disabled; <b>1: Enabled</b> 2-3:Reserved
+ HDC enables the processor to autonomously force components to enter into an idle state to lower effective frequency.
+ This allows for increased package level C6 residency.
+ @note Currently this feature is recommended to be enabled only on win10
+ **/
+ UINT32 HdcControl : 2;
+ UINT32 PowerLimit2 : 1; ///< Enable or Disable short duration Power Limit (PL2). 0: Disable; <b>1: Enable</b>
+ UINT32 TurboPowerLimitLock : 1; ///< MSR 0x610[63] and 0x618[63]: Locks all Turbo power limit settings to read-only; <b>0: Disable</b>; 1: Enable (Lock).
+ UINT32 PowerLimit3DutyCycle : 8; ///< Package PL3 Duty Cycle. Specifies the PL3 duty cycle percentage, Range 0-100. <b>Default: 0</b>.
+ UINT32 PowerLimit3Lock : 1; ///< Package PL3 MSR 615h lock; <b>0: Disable</b>; 1: Enable (Lock).
+ UINT32 PowerLimit4Lock : 1; ///< Package PL4 MSR 601h lock; <b>0: Disable</b>; 1: Enable (Lock).
+ /**
+ Tcc Offset Clamp for Runtime Average Temperature Limit (RATL) allows CPU to throttle below P1.
+ For Y SKU, the recommended default for this policy is <b>1: Enabled</b>, which indicates throttling below P1 is allowed.
+ For all other SKUs the recommended default are <b>0: Disabled</b>.
+ **/
+ UINT32 TccOffsetClamp : 1;
+ UINT32 TccOffsetLock : 1; ///< Tcc Offset Lock for Runtime Average Temperature Limit (RATL) to lock temperature target MSR 1A2h; <b>0: Disabled</b>; 1: Enabled (Lock).
+ UINT32 TurboMode : 1; ///< Enable or Disable Turbo Mode. Disable; <b>1: Enable</b>
+ UINT32 RsvdBits : 10; ///< Reserved for future use.
+ /**
+ 1-Core Ratio Limit: LFM to Fused 1-Core Ratio Limit. For overclocking parts: LFM to Fused 1-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 1-Core Ratio Limit Must be greater than or equal to 2-Core Ratio Limit, 3-Core Ratio Limit, 4-Core Ratio Limit.
+ **/
+ UINT8 OneCoreRatioLimit;
+ /**
+ 2-Core Ratio Limit: LFM to Fused 2-Core Ratio Limit, For overclocking part: LFM to Fused 2-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 2-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 TwoCoreRatioLimit;
+ /**
+ 3-Core Ratio Limit: LFM to Fused 3-Core Ratio Limit, For overclocking part: LFM to Fused 3-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 3-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 ThreeCoreRatioLimit;
+ /**
+ 4-Core Ratio Limit: LFM to Fused 4-Core Ratio Limit, For overclocking part: LFM to Fused 4-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 4-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 FourCoreRatioLimit;
+ UINT8 S3RestoreMsrSwSmiNumber; ///< @deprecated SW SMI number to restore the power mgmt MSRs during S3 resume. Deprecated since revision 2
+ /**
+ TCC Activation Offset. Offset from factory set TCC activation temperature at which the Thermal Control Circuit must be activated.
+ TCC will be activated at (TCC Activation Temperature - TCC Activation Offset), in degrees Celcius.
+ For Y SKU, the recommended default for this policy is <b>10</b>
+ For all other SKUs the recommended default are <b>0</b>, causing TCC to activate at TCC Activation temperature.
+ @note The policy is recommended for validation purpose only.
+ **/
+ UINT8 TccActivationOffset;
+ UINT8 Rsvd[2]; ///< Reserved for future use and config block alignment
+ /**
+ Package Long duration turbo mode power limit (PL1).
+ Default is the TDP power limit of processor. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit1;
+ /**
+ Package Short duration turbo mode power limit (PL2). Allows for short excursions above TDP power limit.
+ Default = 1.25 * TDP Power Limit. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit2Power;
+ /**
+ Package PL3 power limit. PL3 is the CPU Peak Power Occurences Limit.
+ <b>Default: 0</b>. Range 0-65535. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit3;
+ /**
+ Package PL4 power limit. PL4 is a Preemptive CPU Package Peak Power Limit, it will never be exceeded.
+ Power is premptively lowered before limit is reached. <b>Default: 0</b>. Range 0-65535.
+ Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit4;
+ /**
+ Package Long duration turbo mode power limit (PL1) time window in seconds.
+ Used in calculating the average power over time.
+ Mobile: <b> 28s</b>
+ Desktop: <b> 8s</b>
+ Range: 0 - 128s
+ **/
+ UINT32 PowerLimit1Time;
+ /**
+ Power Limit 3 (PL3) time window in milliseconds.
+ Default: <b> 0 - Auto, use hw defaults</b>
+ Range: 0 - 750ms
+ Valid values are: 0,3-8,10,12,14,16,20,24,28,32,40,48,55,56,64
+ **/
+ UINT32 PowerLimit3Time;
+ /**
+ Tcc Offset Time Window can range from 5ms to 448000ms for Runtime Average Temperature Limit (RATL).
+ For Y SKU, the recommended default for this policy is <b>5000: 5 seconds</b>, For all other SKUs the recommended default are <b>0: Disabled</b>
+ **/
+ UINT32 TccOffsetTimeWindowForRatl;
+
+ /**
+ 5-Core Ratio Limit: LFM to Fused 5-Core Ratio Limit, For overclocking part: LFM to Fused 5-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 5-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 FiveCoreRatioLimit;
+ /**
+ 6-Core Ratio Limit: LFM to Fused 6-Core Ratio Limit, For overclocking part: LFM to Fused 6-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 6-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 SixCoreRatioLimit;
+ /**
+ 7-Core Ratio Limit: LFM to Fused 7-Core Ratio Limit, For overclocking part: LFM to Fused 7-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 7-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 SevenCoreRatioLimit;
+ /**
+ 8-Core Ratio Limit: LFM to Fused 8-Core Ratio Limit, For overclocking part: LFM to Fused 8-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 8-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 EightCoreRatioLimit;
+
+} CPU_POWER_MGMT_BASIC_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_BASIC_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h
new file mode 100644
index 0000000000..edb8182db5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h
@@ -0,0 +1,76 @@
+/** @file
+ CPU Power Managment Custom Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_POWER_MGMT_CUSTOM_CONFIG_H_
+#define _CPU_POWER_MGMT_CUSTOM_CONFIG_H_
+
+#define CPU_POWER_MGMT_CUSTOM_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuPowerMgmtCustomConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// Defines the maximum number of custom ratio states supported.
+///
+#define MAX_CUSTOM_RATIO_TABLE_ENTRIES 40
+
+///
+/// Defines the maximum number of custom ConfigTdp entries supported.
+/// @warning: Changing this define would cause DWORD alignment issues in policy structures.
+///
+#define MAX_CUSTOM_CTDP_ENTRIES 3
+
+///
+/// This structure is used to describe the custom processor ratio table desired by the platform.
+///
+typedef struct {
+ UINT16 MaxRatio; ///< The maximum ratio of the custom ratio table.
+ UINT8 NumberOfEntries; ///< The number of custom ratio state entries, ranges from 2 to 16 for a valid custom ratio table.
+ UINT8 Rsvd0; ///< Reserved for DWORD alignment.
+ UINT32 Cpuid; ///< The CPU ID for which this custom ratio table applies.
+ UINT16 StateRatio[MAX_CUSTOM_RATIO_TABLE_ENTRIES]; ///< The processor ratios in the custom ratio table.
+#if (MAX_CUSTOM_RATIO_TABLE_ENTRIES % 2)
+ UINT16 Rsvd1; ///< If there is an odd number of array entries, add padding for dword alignment.
+#endif
+} PPM_CUSTOM_RATIO_TABLE;
+
+///
+/// PPM Custom ConfigTdp Settings
+///
+typedef struct _PPM_CUSTOM_CTDP_TABLE {
+ UINT32 CustomPowerLimit1Time : 8; ///< Short term Power Limit time window value for custom cTDP level.
+ UINT32 CustomTurboActivationRatio : 8; ///< Turbo Activation Ratio for custom cTDP level.
+ UINT32 RsvdBits : 16; ///< Bits reserved for DWORD alignment.
+ UINT16 CustomPowerLimit1; ///< Short term Power Limit value for custom cTDP level. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ UINT16 CustomPowerLimit2; ///< Long term Power Limit value for custom cTDP level. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+} PPM_CUSTOM_CTDP_TABLE;
+
+/**
+ CPU Power Management Custom Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ PPM_CUSTOM_RATIO_TABLE CustomRatioTable; ///< Custom Processor Ration Table Instance
+ PPM_CUSTOM_CTDP_TABLE CustomConfigTdpTable[MAX_CUSTOM_CTDP_ENTRIES]; ///< Custom ConfigTdp Settings Instance
+ UINT32 ConfigTdpLock : 1; ///< Lock the ConfigTdp mode settings from runtime changes; <b>0: Disable</b>; 1: Enable.
+ UINT32 ConfigTdpBios : 1; ///< Configure whether to load Configurable TDP SSDT; <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 30; ///< Reserved for future use
+} CPU_POWER_MGMT_CUSTOM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_CUSTOM_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h
new file mode 100644
index 0000000000..05b1efd5b6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h
@@ -0,0 +1,43 @@
+/** @file
+ CPU Power Management Psys(Platform) Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_POWER_MGMT_PSYS_CONFIG_H_
+#define _CPU_POWER_MGMT_PSYS_CONFIG_H_
+
+#define CPU_POWER_MGMT_PSYS_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuPowerMgmtPsysConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Power Management Psys(Platform) Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 PsysPowerLimit1 : 1; ///< MSR 0x65C[15]: PL1 Enable activates the PL1 value to limit average platform power
+ UINT32 PsysPowerLimit1Time : 8; ///< MSR 0x65C[23:17]: PL1 timewindow in seconds.
+ UINT32 PsysPowerLimit2 : 1; ///< MSR 0x65C[47]: PL2 Enable activates the PL2 value to limit average platform power
+ UINT32 RsvdBits : 22; ///< Reserved for future use.
+ UINT16 PsysPowerLimit1Power; ///< MSR 0x65C[14:0]: Platform PL1 power. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ UINT16 PsysPowerLimit2Power; ///< MSR 0x65C[46:32]]: Platform PL2 power. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ UINT16 PsysPmax; ///< PCODE MMIO Mailbox: Platform Power Pmax. <b>0 - Auto</b> Specified in 1/8 Watt increments. 0-1024 Watts. Value of 800 = 100W.
+ UINT8 Rsvd[2]; ///< Reserved for future use and config block alignment
+} CPU_POWER_MGMT_PSYS_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_PSYS_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h
new file mode 100644
index 0000000000..bf6e829fa3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h
@@ -0,0 +1,145 @@
+/** @file
+ CPU Power Management Test Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_POWER_MGMT_TEST_CONFIG_H_
+#define _CPU_POWER_MGMT_TEST_CONFIG_H_
+
+#define CPU_POWER_MGMT_TEST_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuPowerMgmtTestConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// PPM Package C State Limit
+///
+typedef enum {
+ PkgC0C1 = 0,
+ PkgC2,
+ PkgC3,
+ PkgC6,
+ PkgC7,
+ PkgC7s,
+ PkgC8,
+ PkgC9,
+ PkgC10,
+ PkgCMax,
+ PkgCpuDefault = 254,
+ PkgAuto = 255
+} MAX_PKG_C_STATE;
+
+///
+/// PPM Package C State Time Limit
+///
+typedef enum {
+ TimeUnit1ns = 0,
+ TimeUnit32ns,
+ TimeUnit1024ns,
+ TimeUnit32768ns,
+ TimeUnit1048576ns,
+ TimeUnit33554432ns,
+ TimeUnitMax
+} C_STATE_TIME_UNIT;
+
+///
+/// Custom Power Units. User can choose to enter in watts or 125 milliwatt increments.
+///
+typedef enum {
+ PowerUnitWatts = 0, ///< in Watts.
+ PowerUnit125MilliWatts, ///< in 125 milliwatt increments. Example: 90 power units times 125 mW equals 11.250 W.
+ PowerUnitMax
+} CUSTOM_POWER_UNIT;
+
+///
+/// PPM Interrupt Redirection Mode Selection
+///
+typedef enum {
+ PpmIrmFixedPriority = 0,
+ PpmIrmRoundRobin,
+ PpmIrmHashVector,
+ PpmIrmReserved1,
+ PpmIrmPairFixedPriority,
+ PpmIrmPairRoundRobin,
+ PpmIrmPairHashVector,
+ PpmIrmNoChange
+} PPM_IRM_SETTING;
+
+/**
+ CPU Power Management Test Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ UINT32 Eist : 1; ///< Offset 28-31 Enable or Disable Intel SpeedStep Technology. 0: Disable; <b>1: Enable</b>
+ UINT32 EnergyEfficientPState : 1; ///< Enable or Disable Energy Efficient P-state will be applied in Turbo mode. 0: Disable; <b>1: Enable</b>
+ UINT32 EnergyEfficientTurbo : 1; ///< Enable or Disable Energy Efficient Turbo, will be applied in Turbo mode. 0: Disable; <b>1: Enable</b>
+ UINT32 TStates : 1; ///< Enable or Disable T states; <b>0: Disable</b>; 1: Enable.
+ UINT32 BiProcHot : 1; ///< Enable or Disable Bi-Directional PROCHOT#; 0: Disable; <b>1: Enable</b>.
+ UINT32 DisableProcHotOut : 1; ///< Enable or Disable PROCHOT# signal being driven externally; 0: Disable; <b>1: Enable</b>.
+ UINT32 ProcHotResponse : 1; ///< Enable or Disable PROCHOT# Response; <b>0: Disable</b>; 1: Enable.
+ UINT32 DisableVrThermalAlert : 1; ///< Enable or Disable VR Thermal Alert; <b>0: Disable</b>; 1: Enable.
+ UINT32 AutoThermalReporting : 1; ///< Enable or Disable Thermal Reporting through ACPI tables; 0: Disable; <b>1: Enable</b>.
+ UINT32 ThermalMonitor : 1; ///< Enable or Disable Thermal Monitor; 0: Disable; <b>1: Enable</b>.
+ UINT32 Cx : 1; ///< Enable or Disable CPU power states (C-states). 0: Disable; <b>1: Enable</b>
+ UINT32 PmgCstCfgCtrlLock : 1; ///< If enabled, sets MSR 0xE2[15]; 0: Disable; <b>1: Enable</b>.
+ UINT32 C1e : 1; ///< Enable or Disable Enhanced C-states. 0: Disable; <b>1: Enable</b>
+ UINT32 C1AutoDemotion : 1; ///< Enable or Disable C6/C7 auto demotion to C1. 0: Disabled; <b>1: C1 Auto demotion</b>
+ UINT32 C1UnDemotion : 1; ///< Enable or Disable C1UnDemotion. 0: Disabled; <b>1: C1 Auto undemotion</b>
+ UINT32 C3AutoDemotion : 1; ///< Enable or Disable C6/C7 auto demotion to C3 0: Disabled; <b>1: C3 Auto demotion</b>
+ UINT32 C3UnDemotion : 1; ///< Enable or Disable C3UnDemotion. 0: Disabled; <b>1: C3 Auto undemotion</b>
+ UINT32 PkgCStateDemotion : 1; ///< Enable or Disable Package Cstate Demotion. 0: Disable; <b>1: Enable</b>
+ UINT32 PkgCStateUnDemotion : 1; ///< Enable or Disable Package Cstate UnDemotion. 0: Disable; <b>1: Enable</b>
+ UINT32 CStatePreWake : 1; ///< Enable or Disable CState-Pre wake. 0: Disable; <b>1: Enable</b>
+ UINT32 TimedMwait : 1; ///< Enable or Disable TimedMwait Support. <b>0: Disable</b>; 1: Enable
+ UINT32 CstCfgCtrIoMwaitRedirection : 1; ///< Enable or Disable IO to MWAIT redirection; <b>0: Disable</b>; 1: Enable.
+ UINT32 ProcHotLock : 1; ///< If enabled, sets MSR 0x1FC[23]; <b>0: Disable</b>; 1: Enable.
+ UINT32 RaceToHalt : 1; ///< Enable or Disable Race To Halt feature; 0: Disable; <b>1: Enable </b>. RTH will dynamically increase CPU frequency in order to enter pkg C-State faster to reduce overall power. (RTH is controlled through MSR 1FC bit 20)
+ UINT32 ConfigTdpLevel : 8; ///< Configuration for boot TDP selection; <b>0: TDP Nominal</b>; 1: TDP Down; 2: TDP Up.
+ UINT16 CstateLatencyControl0Irtl; ///< Offset 32-33 Interrupt Response Time Limit of LatencyContol0 MSR 0x60A[9:0].
+ UINT16 CstateLatencyControl1Irtl; ///< Offset 34-35 Interrupt Response Time Limit of LatencyContol1 MSR 0x60B[9:0].
+ UINT16 CstateLatencyControl2Irtl; ///< Offset 36-37 Interrupt Response Time Limit of LatencyContol2 MSR 0x60C[9:0].
+ UINT16 CstateLatencyControl3Irtl; ///< Offset 38-39 Interrupt Response Time Limit of LatencyContol3 MSR 0x633[9:0].
+ UINT16 CstateLatencyControl4Irtl; ///< Offset 40-41 Interrupt Response Time Limit of LatencyContol4 MSR 0x634[9:0].
+ UINT16 CstateLatencyControl5Irtl; ///< Offset 42-43 Interrupt Response Time Limit of LatencyContol5 MSR 0x635[9:0].
+ MAX_PKG_C_STATE PkgCStateLimit; ///< Offset 44 This field is used to set the Max Pkg Cstate. Default set to Auto which limits the Max Pkg Cstate to deep C-state.
+ C_STATE_TIME_UNIT CstateLatencyControl0TimeUnit; ///< Offset 45 TimeUnit for Latency Control0 MSR 0x60A[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl1TimeUnit; ///< Offset 46 TimeUnit for Latency Control1 MSR 0x60B[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl2TimeUnit; ///< Offset 47 TimeUnit for Latency Control2 MSR 0x60C[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl3TimeUnit; ///< Offset 48 TimeUnit for Latency Control3 MSR 0x633[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl4TimeUnit; ///< Offset 49 TimeUnit for Latency Control4 MSR 0x634[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl5TimeUnit; ///< Offset 50 TimeUnit for Latency Control5 MSR 0x635[12:10]; <b>2: 1024ns</b>.
+ /**
+ Offset 51 Default power unit in watts or in 125 milliwatt increments.
+ - 0: PowerUnitWatts.
+ - <b>1: PowerUnit125MilliWatts</b>.
+ **/
+ CUSTOM_POWER_UNIT CustomPowerUnit;
+ /**
+ Offset 52 Interrupt Redirection Mode Select.
+ - 0: Fixed priority.
+ - 1: Round robin.
+ - 2: Hash vector.
+ - <b>4: PAIR with fixed priority</b>.
+ - 5: PAIR with round robin.
+ - 6: PAIR with hash vector.
+ - 7: No change.
+ **/
+ PPM_IRM_SETTING PpmIrmSetting;
+ UINT8 Rsvd[4]; ///< Offset 53-56 Reserved for future use and config block alignment
+} CPU_POWER_MGMT_TEST_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_TEST_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtVrConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtVrConfig.h
new file mode 100644
index 0000000000..ad4ed76250
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtVrConfig.h
@@ -0,0 +1,104 @@
+/** @file
+ CPU Power Management VR Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_POWER_MGMT_VR_CONFIG_H_
+#define _CPU_POWER_MGMT_VR_CONFIG_H_
+
+#define CPU_POWER_MGMT_VR_CONFIG_REVISION 2
+
+extern EFI_GUID gCpuPowerMgmtVrConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// Defines the maximum number of VR domains supported.
+/// @warning: Changing this define would cause DWORD alignment issues in policy structures.
+///
+#define MAX_NUM_VRS 4
+
+/**
+ CPU Power Management VR Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Deprecate SendVrMbxCmd
+ - Add SendVrMbxCmd1 for VR specific mailbox commands:
+ 001b: MPS IMPV8 VR mailbox command.
+ 010b: VR specific command sent for PS4 exit issue.
+ 100b: VR specific command sent for MPS VR decay issue.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 AcousticNoiseMitigation : 1; ///< Enable or Disable Acoustic Noise Mitigation feature. <b>0: Disabled</b>; 1: Enabled
+ UINT32 FastPkgCRampDisableIa : 1; ///< Disable Fast Slew Rate for Deep Package C States for VR IA domain based on Acoustic Noise Mitigation feature enabled. <b>0: False</b>; 1: True
+ UINT32 FastPkgCRampDisableGt : 1; ///< Disable Fast Slew Rate for Deep Package C States for VR GT domain based on Acoustic Noise Mitigation feature enabled. <b>0: False</b>; 1: True
+ UINT32 FastPkgCRampDisableSa : 1; ///< Disable Fast Slew Rate for Deep Package C States for VR SA domain based on Acoustic Noise Mitigation feature enabled. <b>0: False</b>; 1: True
+ UINT32 SlowSlewRateForIa : 2; ///< Slew Rate configuration for Deep Package C States for VR IA domain based on Acoustic Noise Mitigation feature enabled. <b>0: Fast/2</b>; 1: Fast/4; 2: Fast/8; 3: Fast/16
+ UINT32 SlowSlewRateForGt : 2; ///< Slew Rate configuration for Deep Package C States for VR GT domain based on Acoustic Noise Mitigation feature enabled. <b>0: Fast/2</b>; 1: Fast/4; 2: Fast/8; 3: Fast/16
+ UINT32 SlowSlewRateForSa : 2; ///< Slew Rate configuration for Deep Package C States for VR SA domain based on Acoustic Noise Mitigation feature enabled. <b>0: Fast/2</b>; 1: Fast/4; 2: Fast/8; 3: Fast/16
+ /**
+ Deprecated:
+ VR specific mailbox commands.
+ <b>00b - no VR specific command sent.</b>
+ 01b - A VR mailbox command specifically for the MPS IMPV8 VR will be sent.
+ 10b - VR specific command sent for PS4 exit issue.
+ 11b - Reserved.
+ **/
+ UINT32 SendVrMbxCmd : 2;
+ /**
+ VR specific mailbox commands.
+ <b>000b - no VR specific command sent.</b>
+ 001b - A VR mailbox command specifically for the MPS IMPV8 VR will be sent.
+ 010b - VR specific command sent for PS4 exit issue.
+ 100b - VR specific command sent for MPS VR decay issue.
+ Bitwise encoding. Allows for any combination of commands to be sent.
+ example 110b - to send both PS4 exit issue and MPS VR decay issue commands.
+ **/
+ UINT32 SendVrMbxCmd1 : 3;
+ UINT32 RsvdBits : 17; ///< Reserved for future use.
+ UINT8 PsysSlope; ///< PCODE MMIO Mailbox: Platform Psys slope correction. <b>0 - Auto</b> Specified in 1/100 increment values. Range is 0-200. 125 = 1.25.
+ UINT8 PsysOffset; ///< PCODE MMIO Mailbox: Platform Psys offset correction. <b>0 - Auto</b> Units 1/4, Range 0-255. Value of 100 = 100/4 = 25 offset.
+ UINT8 Rsvd[2]; ///< Reserved for future use and config block alignment
+ /** @name VR Settings
+ The VR related settings are sorted in an array where each index maps to the VR domain as defined below:
+ - 0 = System Agent VR
+ - 1 = IA Core VR
+ - 2 = GT unsliced VR
+ - 3 = GT sliced VR
+
+ The VR settings for a given domain must be populated in the appropriate index.
+ **/
+ ///@{
+ UINT16 TdcPowerLimit[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Thermal Design Current current limit. Specified in 1/8A units. Range is 0-4095. 1000 = 125A. <b>0: 0 Amps</b>
+ UINT16 AcLoadline[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: AcLoadline in 1/100 mOhms (ie. 1250 = 12.50 mOhm); Range is 0-6249. <b>Intel Recommended Defaults vary by domain and SKU.</b>
+ UINT16 DcLoadline[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: DcLoadline in 1/100 mOhms (ie. 1250 = 12.50 mOhm); Range is 0-6249.<b>Intel Recommended Defaults vary by domain and SKU.</b>
+ UINT16 Psi1Threshold[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Power State 1 current cuttof in 1/4 Amp increments. Range is 0-128A. <b>Default Value = 20A.</b>
+ UINT16 Psi2Threshold[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Power State 2 current cuttof in 1/4 Amp increments. Range is 0-128A. <b>Default Value = 5A.</b>
+ UINT16 Psi3Threshold[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Power State 3 current cuttof in 1/4 Amp increments. Range is 0-128A. <b>Default Value = 1A.</b>
+ UINT8 Psi3Enable[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Power State 3 enable/disable; 0: Disable; <b>1: Enable</b>.
+ UINT8 Psi4Enable[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Power State 4 enable/disable; 0: Disable; <b>1: Enable</b>.
+ UINT8 ImonSlope[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Imon slope correction. Specified in 1/100 increment values. Range is 0-200. 125 = 1.25. <b>0: Auto</b>
+ INT16 ImonOffset[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Imon offset correction. Value is a 2's complement signed integer. Units 1/1000, Range 0-63999. For an offset = 12.580, use 12580. <b>0: Auto</b>
+ UINT16 IccMax[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: VR Icc Max limit. 0-255A in 1/4 A units. 400 = 100A. <b>Default: 0 - Auto, no override</b>
+ UINT16 VrVoltageLimit[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: VR Voltage Limit. Range is 0-7999mV.
+ UINT8 VrConfigEnable[MAX_NUM_VRS]; ///< Enable/Disable BIOS configuration of VR; 0: Disable; <b>1: Enable.</b>
+ UINT8 TdcEnable[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Thermal Design Current enable/disable; <b>0: Disable; </b>1: Enable
+ UINT8 TdcTimeWindow[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Thermal Design Current time window. Defined in milli seconds. <b>1ms default</b>
+ UINT8 TdcLock[MAX_NUM_VRS]; ///< PCODE MMIO Mailbox: Thermal Design Current Lock; <b>0: Disable</b>; 1: Enable.
+ ///@}
+} CPU_POWER_MGMT_VR_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_VR_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h
new file mode 100644
index 0000000000..2b1fa5b3a5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h
@@ -0,0 +1,122 @@
+/** @file
+ CPU Test Config Block.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_TEST_CONFIG_H_
+#define _CPU_TEST_CONFIG_H_
+
+#define CPU_TEST_CONFIG_REVISION 2
+
+extern EFI_GUID gCpuTestConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Test Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+
+ <b>Revision 2</b>:
+ - Deprecated and moved Hyperthreading to CPU_CONFIG_LIB_PREMEM_CONFIG
+ - Deprecated and moved CpuRatioOverride to CPU_CONFIG_LIB_PREMEM_CONFIG
+ - Deprecated and moved CpuRatio to CPU_CONFIG_LIB_PREMEM_CONFIG
+ - Deprecated and moved ActiveCoreCount to CPU_CONFIG_LIB_PREMEM_CONFIG
+ - Deprecated and moved JtagC10PowerGateDisable to CPU_CONFIG_LIB_PREMEM_CONFIG
+
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 HyperThreading : 1; ///< Enable or Disable Hyper Threading; 0: Disable; <b>1: Enable</b>.
+ /**
+ @deprecated since revision 2. Moved to CPU_CONFIG_LIB_PREMEM_CONFIG
+ Enable or disable override of default max non-turbo ratio. If enabled, BIOS will take the value specified in
+ CpuRatio policy and updates the max non-turbo ratio. See policy CpuRatio for more details.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 CpuRatioOverride : 1; ///< @deprecated since revision 2. Moved to CPU_CONFIG_LIB_PREMEM_CONFIG
+ UINT32 MlcStreamerPrefetcher : 1; ///< Enable or Disable MLC Streamer Prefetcher; 0: Disable; <b>1: Enable</b>.
+ UINT32 MlcSpatialPrefetcher : 1; ///< Enable or Disable MLC Spatial Prefetcher; 0: Disable; <b>1: Enable</b>.
+ UINT32 MonitorMwaitEnable : 1; ///< Enable or Disable Monitor /MWAIT instructions; 0: Disable; <b>1: Enable</b>.
+ UINT32 MachineCheckEnable : 1; ///< Enable or Disable initialization of machine check registers; 0: Disable; <b>1: Enable</b>.
+ UINT32 DebugInterfaceEnable : 1; ///< Enable or Disable processor debug features; <b>0: Disable</b>; 1: Enable.
+ UINT32 DebugInterfaceLockEnable : 1; ///< Lock or Unlock debug interface features; 0: Disable; <b>1: Enable</b>.
+ /**
+ AP Idle Manner of waiting - Manner of which APs are waiting to be tasked by MP Services
+ - 1: HALT loop
+ - <b>2: MWAIT loop</b>
+ - 3: Run loop
+ **/
+ UINT32 ApIdleManner : 2;
+ /**
+ Settings for AP Handoff to OS - Type of loop AP is placed in before handing control to OS.
+ - 1: HALT loop
+ - <b>2: MWAIT loop</b>
+ **/
+ UINT32 ApHandoffManner : 2;
+ /**
+ @deprecated since revision 2. Moved to CPU_CONFIG_LIB_PREMEM_CONFIG
+ Number of processor cores to enable.
+ - <b> 0: All cores</b>
+ - 1: 1 core
+ - 2: 2 cores
+ - 3: 3 cores
+ **/
+ UINT32 ActiveCoreCount : 3; ///< @deprecated since revision 2. Moved to CPU_CONFIG_LIB_PREMEM_CONFIG
+ UINT32 JtagC10PowerGateDisable : 1; ///< Power JTAG in C10 and deeper power states; <b>0: Disable</b>; 1: Enable.
+ UINT32 ProcTraceOutputScheme : 1; ///< Control on Processor Trace output scheme; <b>0: Single Range Output</b>; 1: ToPA Output.
+ UINT32 ProcTraceEnable : 1; ///< Enable or Disable Processor Trace feature; <b>0: Disable</b>; 1: Enable.
+ /**
+ Memory region allocation for Processor Trace.
+ Total memory required is equal to the requested value * 2 (for memory alignment) * number of active processor threads.
+ Based on MEMORY_CONFIG_NO_CRC.PlatformMemorySize default, up to 2MB policy setting with up to 8 active threads is supported (32MB memory total).
+ For larger size requests, MEMORY_CONFIG_NO_CRC.PlatformMemorySize needs to be increased.
+ - 0: 4K
+ - 1: 8K
+ - 2: 16K
+ - 3: 32K
+ - 4: 64K
+ - 5: 128K
+ - 6: 256K
+ - 7: 512K
+ - 8: 1M
+ - 9: 2M
+ - 10: 4M
+ - 11: 8M
+ - 12: 16M
+ - 13: 32M
+ - 14: 64M
+ - 15: 128M
+ - <b>255: Disable</b>
+ **/
+ UINT32 ProcTraceMemSize : 8;
+ UINT32 ThreeStrikeCounterDisable : 1; ///< Disable Three strike counter; <b>0: FALSE</b>; 1: TRUE.
+ /**
+ This policy should be used to enable or disable Voltage Optimization feature.
+ Recommended defaults:
+ Enable - For Mobile SKUs(U/Y)
+ Disable - Rest of all SKUs other than Mobile.
+ **/
+ UINT32 VoltageOptimization : 1;
+ UINT32 RsvdBits : 4; ///< Reserved for future use
+ /**
+ @deprecated since revision 2. Moved to CPU_CONFIG_LIB_PREMEM_CONFIG
+ CpuRatio - When CpuRatioOverride is enabled, max non-turbo ratio (Flexible Ratio Boot) is set to CpuRatio.
+ **/
+ UINT8 CpuRatio;
+ UINT8 Rsvd[3]; ///< Reserved for future use
+} CPU_TEST_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_TEST_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuAccess.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuAccess.h
new file mode 100644
index 0000000000..dc62fea6eb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuAccess.h
@@ -0,0 +1,21 @@
+/** @file
+ Macros to simplify and abstract the interface to CPU configuration.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPUACCESS_H_
+#define _CPUACCESS_H_
+
+#include "CpuRegs.h"
+#include "CpuDataStruct.h"
+#include "CpuPowerMgmt.h"
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuDataStruct.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuDataStruct.h
new file mode 100644
index 0000000000..e7caafa416
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuDataStruct.h
@@ -0,0 +1,194 @@
+/** @file
+ This file declares various data structures used in CPU reference code.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CPU_DATA_STRUCT_H
+#define _CPU_DATA_STRUCT_H
+
+//
+// The reason for changing the state of the processor Only applies to Disabling processors.
+// In future, we can add add/remove support
+//
+#define CPU_CAUSE_NOT_DISABLED 0x0000
+#define CPU_CAUSE_INTERNAL_ERROR 0x0001
+#define CPU_CAUSE_THERMAL_ERROR 0x0002
+#define CPU_CAUSE_SELFTEST_FAILURE 0x0004
+#define CPU_CAUSE_PREBOOT_TIMEOUT 0x0008
+#define CPU_CAUSE_FAILED_TO_START 0x0010
+#define CPU_CAUSE_CONFIG_ERROR 0x0020
+#define CPU_CAUSE_USER_SELECTION 0x0080
+#define CPU_CAUSE_BY_ASSOCIATION 0x0100
+#define CPU_CAUSE_UNSPECIFIED 0x8000
+
+typedef UINT32 CPU_STATE_CHANGE_CAUSE;
+
+///
+/// The data structure is used retrieve data required for MP initialization during S3 resume.
+///
+typedef struct {
+ BOOLEAN APState; ///< Indicates whether the newstate of the AP is enabled or disabled.
+ BOOLEAN S3BootPath; ///< TRUE: S3 Boot path. FALSE: Regular boot path.
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer; ///< Buffer location used during AP Initialization
+ EFI_PHYSICAL_ADDRESS GdtrProfile; ///< Address of Global Descriptor Table
+ EFI_PHYSICAL_ADDRESS IdtrProfile; ///< address of Interrupt Descriptor Table
+ EFI_PHYSICAL_ADDRESS CpuPrivateData; ///< Address of CPU_PRIVATE_DATA structure
+ EFI_PHYSICAL_ADDRESS StackAddress; ///< Address of APs's stacks
+ EFI_PHYSICAL_ADDRESS SmramBase; ///< @deprecated Address of SMRAM base as seen by software executing on the processors
+ EFI_PHYSICAL_ADDRESS SmmStartImageBase; ///< @deprecated Address of SMM Start Image Base
+ UINT32 SmmStartImageSize; ///< @deprecated Size of SMM Start Image
+ UINT32 NumberOfCpus; ///< Number of processors
+} ACPI_CPU_DATA;
+
+///
+/// CPU information stored in SMRAM during DXE.
+///
+typedef struct {
+ //
+ // Guid as Signature.
+ //
+ EFI_GUID HeaderGuid;
+ EFI_PHYSICAL_ADDRESS AcpiCpuPointer;
+ ACPI_CPU_DATA AcpiCpuData;
+
+ //
+ // It points the data defined below.
+ //
+ EFI_PHYSICAL_ADDRESS GdtrProfileOffset;
+ EFI_PHYSICAL_ADDRESS GdtOffset;
+ EFI_PHYSICAL_ADDRESS IdtrProfileOffset;
+ EFI_PHYSICAL_ADDRESS IdtOffset;
+ EFI_PHYSICAL_ADDRESS CpuPrivateDataOffset;
+ EFI_PHYSICAL_ADDRESS S3BspMtrrTableOffset;
+ ///
+ /// We need put all the data buffer here as well.
+ /// These data will be copied to original location in S3.
+ ///
+ //
+ // DataBuffer size
+ //
+ UINT32 GdtrProfileSize;
+ UINT32 GdtSize;
+ UINT32 IdtrProfileSize;
+ UINT32 IdtSize;
+ UINT32 CpuPrivateDataSize;
+ UINT32 S3BspMtrrTableSize;
+} SMRAM_CPU_DATA;
+
+///
+/// Structure to hold the return value of AsmCpuid instruction
+///
+typedef struct {
+ UINT32 RegEax; ///< Value of EAX.
+ UINT32 RegEbx; ///< Value of EBX.
+ UINT32 RegEcx; ///< Value of ECX.
+ UINT32 RegEdx; ///< Value of EDX.
+} EFI_CPUID_REGISTER;
+
+///
+/// Structure to describe microcode header
+///
+typedef struct {
+ UINT32 HeaderVersion; ///< Version number of the update header.
+ UINT32 UpdateRevision; ///< Unique version number for the update.
+ UINT32 Date; ///< Date of the update creation.
+ UINT32 ProcessorId; ///< Signature of the processor that requires this update.
+ UINT32 Checksum; ///< Checksum of update data and header.
+ UINT32 LoaderRevision; ///< Version number of the microcode loader program.
+ UINT32 ProcessorFlags; ///< Lower 4 bits denoting platform type information.
+ UINT32 DataSize; ///< Size of encoded data in bytes.
+ UINT32 TotalSize; ///< Total size of microcode update in bytes.
+ UINT8 Reserved[12]; ///< Reserved bits.
+} CPU_MICROCODE_HEADER;
+
+///
+/// Structure to describe the extended signature table header of the microcode update
+///
+typedef struct {
+ UINT32 ExtendedSignatureCount; ///< Number of extended signature structures.
+ UINT32 ExtendedTableChecksum; ///< Checksum of update extended processor signature table.
+ UINT8 Reserved[12]; ///< Reserved bits.
+} CPU_MICROCODE_EXTENDED_TABLE_HEADER;
+
+///
+/// Structure to describe the data of the extended table of the microcode update
+///
+typedef struct {
+ UINT32 ProcessorSignature; ///< Extended signature of the processor that requires this update
+ UINT32 ProcessorFlag; ///< Lower 4 bits denoting platform type information
+ UINT32 ProcessorChecksum; ///< checksum of each of the extended update
+} CPU_MICROCODE_EXTENDED_TABLE;
+
+#pragma pack(1)
+///
+/// MSR_REGISTER definition as a Union of QWORDS, DWORDS and BYTES
+///
+typedef union _MSR_REGISTER {
+ UINT64 Qword; ///< MSR value in 64 bit QWORD.
+
+ ///
+ /// MSR value represented in two DWORDS
+ ///
+ struct {
+ UINT32 Low; ///< Lower DWORD of the 64 bit MSR value.
+ UINT32 High; ///< Higher DWORD of the 64 bit MSR value.
+ } Dwords;
+
+ ///
+ /// MSR value represented in eight bytes.
+ ///
+ struct {
+ UINT8 FirstByte; ///< First byte of the 64 bit MSR value.
+ UINT8 SecondByte; ///< Second byte of the 64 bit MSR value.
+ UINT8 ThirdByte; ///< Third byte of the 64 bit MSR value.
+ UINT8 FouthByte; ///< Fourth byte of the 64 bit MSR value.
+ UINT8 FifthByte; ///< Fifth byte of the 64 bit MSR value.
+ UINT8 SixthByte; ///< Sixth byte of the 64 bit MSR value.
+ UINT8 SeventhByte; ///< Seventh byte of the 64 bit MSR value.
+ UINT8 EighthByte; ///< Eigth byte of the 64 bit MSR value.
+ } Bytes;
+} MSR_REGISTER;
+
+///
+/// Store BIST data for BSP.
+///
+typedef struct {
+ UINT32 ApicId; ///< APIC ID
+ UINT32 Health; ///< BIST result
+} BIST_HOB_DATA;
+
+///
+/// Processor trace buffer size selection.
+///
+typedef enum {
+ Enum4K = 0,
+ Enum8K,
+ Enum16K,
+ Enum32K,
+ Enum64K,
+ Enum128K,
+ Enum256K,
+ Enum512K,
+ Enum1M,
+ Enum2M,
+ Enum4M,
+ Enum8M,
+ Enum16M,
+ Enum32M,
+ Enum64M,
+ Enum128M,
+ EnumProcTraceMemDisable
+} PROC_TRACE_MEM_SIZE;
+
+#pragma pack()
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h
new file mode 100644
index 0000000000..a8ee41ec99
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h
@@ -0,0 +1,29 @@
+/** @file
+ CPU Policy structure definition which will contain several config blocks during runtime.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_POLICY_COMMON_H_
+#define _CPU_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+#include <ConfigBlock/CpuOverclockingConfig.h>
+#include <ConfigBlock/CpuConfig.h>
+#include <ConfigBlock/CpuPidTestConfig.h>
+#include <ConfigBlock/CpuPowerMgmtBasicConfig.h>
+#include <ConfigBlock/CpuPowerMgmtCustomConfig.h>
+#include <ConfigBlock/CpuPowerMgmtPsysConfig.h>
+#include <ConfigBlock/CpuPowerMgmtTestConfig.h>
+#include <ConfigBlock/CpuPowerMgmtVrConfig.h>
+#include <ConfigBlock/CpuTestConfig.h>
+#include <ConfigBlock/CpuConfigLibPreMemConfig.h>
+
+#endif // _CPU_POLICY_COMMON_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPowerMgmt.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPowerMgmt.h
new file mode 100644
index 0000000000..612b166010
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuPowerMgmt.h
@@ -0,0 +1,106 @@
+/** @file
+ This file contains define definitions specific to processor
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _POWER_MGMT_DEFINITIONS_H_
+#define _POWER_MGMT_DEFINITIONS_H_
+
+#define CSTATE_SUPPORTED 0x1
+#define ENHANCED_CSTATE_SUPPORTED 0x2
+#define C6_C7_SHORT_LATENCY_SUPPORTED 0x01
+#define C6_C7_LONG_LATENCY_SUPPORTED 0x02
+#define C7s_SHORT_LATENCY_SUPPORTED 0x03
+#define C7s_LONG_LATENCY_SUPPORTED 0x04
+//
+// Voltage offset definitions
+//
+#define OC_LIB_OFFSET_ADAPTIVE 0
+#define OC_LIB_OFFSET_OVERRIDE 1
+//
+// Platform Power Management Flags Bit Definitions:
+// These defines are also used in CPU0CST.ASL to check platform configuration
+// and build C-state table accordingly.
+//
+#define PPM_EIST BIT0 ///< Enhanced Intel Speed Step Technology.
+#define PPM_C1 BIT1 ///< C1 enabled, supported.
+#define PPM_C1E BIT2 ///< C1E enabled.
+#define PPM_C3 BIT3 ///< C3 enabled, supported.
+#define PPM_C6 BIT4 ///< C6 enabled, supported.
+#define PPM_C7 BIT5 ///< C7 enabled, supported.
+#define PPM_C7S BIT6 ///< C7S enabled, supported
+#define PPM_TM BIT7 ///< Adaptive Thermal Monitor.
+#define PPM_TURBO BIT8 ///< Long duration turbo mode
+#define PPM_CMP BIT9 ///< CMP.
+#define PPM_TSTATES BIT10 ///< CPU throttling states
+#define PPM_MWAIT_EXT BIT11 ///< MONITIOR/MWAIT Extensions supported.
+#define PPM_EEPST BIT12 ///< Energy efficient P-State Feature enabled
+#define PPM_TSTATE_FINE_GRAINED BIT13 ///< Fine grained CPU Throttling states
+#define PPM_CD BIT14 ///< Deep Cstate - C8/C9/C10
+#define PPM_TIMED_MWAIT BIT15 ///< Timed Mwait support
+#define C6_LONG_LATENCY_ENABLE BIT16 ///< 1=C6 Long and Short,0=C6 Short only
+#define C7_LONG_LATENCY_ENABLE BIT17 ///< 1=C7 Long and Short,0=C7 Short only
+#define C7s_LONG_LATENCY_ENABLE BIT18 ///< 1=C7s Long and Short,0=C7s Short only
+#define PPM_C8 BIT19 ///< 1= C8 enabled/supported
+#define PPM_C9 BIT20 ///< 1= C9 enabled/supported
+#define PPM_C10 BIT21 ///< 1= C10 enabled/supported
+#define PPM_HWP BIT22 ///< 1= HWP enabled/supported
+#define PPM_HWP_LVT BIT23 ///< 1= HWP LVT enabled/supported
+#define PPM_OC_UNLOCKED BIT24 ///< 1= Overclocking fully unlocked
+
+#define PPM_C_STATES 0x7A ///< PPM_C1 + PPM_C3 + PPM_C6 + PPM_C7 + PPM_C7S
+#define C3_LATENCY 0x4E
+#define C6_C7_SHORT_LATENCY 0x76
+#define C6_C7_LONG_LATENCY 0x94
+#define C8_LATENCY 0xFA
+#define C9_LATENCY 0x14C
+#define C10_LATENCY 0x3F2
+
+//
+// The following definitions are based on assumed location for the ACPI
+// Base Address. Modify as necessary base on platform-specific requirements.
+//
+#define PCH_ACPI_PBLK 0x1810
+#define PCH_ACPI_LV2 0x1814
+#define PCH_ACPI_LV3 0x1815
+#define PCH_ACPI_LV4 0x1816
+#define PCH_ACPI_LV6 0x1818
+#define PCH_ACPI_LV5 0x1817
+#define PCH_ACPI_LV7 0x1819
+
+//
+// C-State Latency (us) and Power (mW) for C1
+//
+#define C1_LATENCY 1
+#define C1_POWER 0x3E8
+#define C3_POWER 0x1F4
+#define C6_POWER 0x15E
+#define C7_POWER 0xC8
+#define C8_POWER 0xC8
+#define C9_POWER 0xC8
+#define C10_POWER 0xC8
+
+
+#define PID_DOMAIN_KP 0
+#define PID_DOMAIN_KI 1
+#define PID_DOMAIN_KD 2
+#define MAILBOX_PARAM_1_OFFSET 8
+
+///
+/// VR Domain Definitions
+///
+#define SKL_VR_DOMAIN_SA 0x0
+#define SKL_VR_DOMAIN_IA 0x1
+#define SKL_VR_DOMAIN_GTUS 0x2
+#define SKL_VR_DOMAIN_GTS 0x3
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuRegs.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuRegs.h
new file mode 100644
index 0000000000..21b6dd6f4b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/CpuRegs.h
@@ -0,0 +1,330 @@
+/** @file
+ Register names for CPU registers
+
+ <b>Conventions</b>
+ - Definitions beginning with "MSR_" are MSRs
+ - Definitions beginning with "R_" are registers
+ - Definitions beginning with "B_" are bits within registers
+ - Definitions beginning with "V_" are meaningful values of bits within the registers
+ - Definitions beginning with "S_" are register sizes
+ - Definitions beginning with "N_" are the bit position
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_REGS_H_
+#define _CPU_REGS_H_
+
+///
+/// Arch-specific MSR defines in SDM, but not defined for SKL
+/// @{
+
+#define MSR_PLATFORM_INFO 0x000000CE
+#define N_PLATFORM_INFO_MIN_RATIO 40
+#define B_PLATFORM_INFO_RATIO_MASK 0xFF
+#define N_PLATFORM_INFO_MAX_RATIO 8
+#define B_MSR_PLATFORM_INFO_BIOSGUARD_AVAIL BIT35
+#define N_MSR_PLATFORM_INFO_CONFIG_TDP_NUM_LEVELS_OFFSET 33
+#define V_CONFIG_TDP_NUM_LEVELS_MASK (BIT34 | BIT33)
+#define B_PLATFORM_INFO_TDC_TDP_LIMIT BIT29
+#define N_PLATFORM_INFO_RATIO_LIMIT 28
+#define B_PLATFORM_INFO_RATIO_LIMIT BIT28
+#define B_PLATFORM_INFO_SAMPLE_PART BIT27
+#define B_PLATFORM_INFO_SMM_SAVE_CONTROL BIT16
+#define N_PLATFORM_INFO_PROG_TCC_ACTIVATION_OFFSET 30
+#define B_PLATFORM_INFO_PROG_TCC_ACTIVATION_OFFSET BIT30
+#define B_PLATFORM_INFO_TIMED_MWAIT_SUPPORTED BIT37
+#define B_PLATFORM_INFO_EDRAM_EN BIT57
+
+//
+// MSR_BROADWELL_PKG_CST_CONFIG_CONTROL: related defines
+//
+#define B_TIMED_MWAIT_ENABLE BIT31 ///< @todo Remove when bitfield definition is available.
+#define V_CSTATE_LIMIT_C1 0x01
+#define V_CSTATE_LIMIT_C3 0x02
+#define V_CSTATE_LIMIT_C6 0x03
+#define V_CSTATE_LIMIT_C7 0x04
+#define V_CSTATE_LIMIT_C7S 0x05
+#define V_CSTATE_LIMIT_C8 0x06
+#define V_CSTATE_LIMIT_C9 0x07
+#define V_CSTATE_LIMIT_C10 0x08
+
+#define MSR_PMG_IO_CAPTURE_BASE 0x000000E4
+#define B_MSR_PMG_CST_RANGE (BIT18 | BIT17 | BIT16)
+#define V_IO_CAPT_LVL2 (0x0 << 16) ///< C3
+#define V_IO_CAPT_LVL3 (0x1 << 16) ///< C6
+#define V_IO_CAPT_LVL4 (0x2 << 16) ///< C7
+#define V_IO_CAPT_LVL5 (0x3 << 16) ///< C8
+#define V_IO_CAPT_LVL6 (0x4 << 16) ///< C9
+#define V_IO_CAPT_LVL7 (0x5 << 16) ///< C10
+#define V_IO_CAPT_LVL2_BASE_ADDR_MASK 0xFFFF
+
+#define MSR_TEMPERATURE_TARGET 0x000001A2
+#define B_MSR_TEMPERATURE_TARGET_TCC_OFFSET_LOCK BIT31
+#define N_MSR_TEMPERATURE_TARGET_TCC_OFFSET_LIMIT 24
+#define V_MSR_TEMPERATURE_TARGET_TCC_ACTIVATION_OFFSET_MASK 0x3F
+#define N_MSR_TEMPERATURE_TARGET_TCC_ACTIVATION_TEMPERATURE_OFFSET (16)
+#define B_MSR_TEMPERATURE_TARGET_TCC_ACTIVATION_TEMPERATURE_MASK (0xFF << 16)
+#define N_MSR_TEMPERATURE_TARGET_FAN_TEMP_TARGET_OFFSET 8
+#define B_MSR_TEMPERATURE_TARGET_FAN_TEMP_TARGET_OFFSET (0xFF << 8)
+#define B_MSR_TEMPERATURE_TARGET_TCC_OFFSET_TIME_WINDOW (0x7F)
+#define B_MSR_TEMPERATURE_TARGET_TCC_OFFSET_MASK 0xFF
+#define B_MSR_TEMPERATURE_TARGET_TCC_OFFSET_CLAMP_BIT BIT7
+
+
+#define MSR_TURBO_RATIO_LIMIT 0x000001AD
+#define N_MSR_TURBO_RATIO_LIMIT_1C 0
+#define B_MSR_TURBO_RATIO_LIMIT_1C (0xFFULL << 0)
+#define N_MSR_TURBO_RATIO_LIMIT_2C 8
+#define B_MSR_TURBO_RATIO_LIMIT_2C (0xFFULL << 8)
+#define N_MSR_TURBO_RATIO_LIMIT_3C 16
+#define B_MSR_TURBO_RATIO_LIMIT_3C (0xFFULL << 16)
+#define N_MSR_TURBO_RATIO_LIMIT_4C 24
+#define B_MSR_TURBO_RATIO_LIMIT_4C (0xFFULL << 24)
+#define N_MSR_TURBO_RATIO_LIMIT_5C 32
+#define B_MSR_TURBO_RATIO_LIMIT_5C (0xFFULL << 32)
+#define N_MSR_TURBO_RATIO_LIMIT_6C 40
+#define B_MSR_TURBO_RATIO_LIMIT_6C (0xFFULL << 40)
+#define N_MSR_TURBO_RATIO_LIMIT_7C 48
+#define B_MSR_TURBO_RATIO_LIMIT_7C (0xFFULL << 48)
+#define N_MSR_TURBO_RATIO_LIMIT_8C 56
+#define B_MSR_TURBO_RATIO_LIMIT_8C (0xFFULL << 56)
+
+#define MSR_IA32_FEATURE_CONFIG 0x0000013C
+#define B_IA32_FEATURE_CONFIG_AES_DIS BIT1
+#define B_IA32_FEATURE_CONFIG_LOCK BIT0
+
+
+//
+// MSRs for SMM State Save Register
+//
+#define MSR_SMM_MCA_CAP 0x0000017D
+#define B_TARGETED_SMI BIT56
+#define N_TARGETED_SMI 56
+#define B_SMM_CPU_SVRSTR BIT57
+#define N_SMM_CPU_SVRSTR 57
+#define B_SMM_CODE_ACCESS_CHK BIT58
+#define N_SMM_CODE_ACCESS_CHK 58
+#define B_LONG_FLOW_INDICATION BIT59
+#define N_LONG_FLOW_INDICATION 59
+#define MSR_SMM_FEATURE_CONTROL 0x000004E0
+#define B_SMM_FEATURE_CONTROL_LOCK BIT0
+#define B_SMM_CPU_SAVE_EN BIT1
+#define B_SMM_CODE_CHK_EN BIT2
+
+/// @}
+
+
+///
+/// Bit defines for MSRs defined in UefiCpuPkg/Include/Register/ArchitecturalMsr.h.
+/// @{
+
+//
+// Number of fixed MTRRs
+//
+#define V_FIXED_MTRR_NUMBER 11
+
+
+//
+// Number of variable MTRRs
+//
+#define V_MAXIMUM_VARIABLE_MTRR_NUMBER 10
+
+//
+// Bit defines for MSR_IA32_MTRR_DEF_TYPE
+//
+#define B_CACHE_MTRR_VALID BIT11
+#define B_CACHE_FIXED_MTRR_VALID BIT10
+
+//
+// Bit defines for MSR_IA32_DEBUG_INTERFACE
+//
+#define B_DEBUG_INTERFACE_ENABLE BIT0
+#define B_DEBUG_INTERFACE_LOCK BIT30
+#define B_DEBUG_INTERFACE_DEBUG_STATUS BIT31
+
+/// @}
+
+///
+/// Other defines
+///
+
+//
+// Local APIC defines
+//
+#define APIC_REGISTER_LOCAL_ID_OFFSET 0x00000020
+#define APIC_REGISTER_APIC_VERSION_OFFSET 0x00000030
+#define APIC_REGISTER_SPURIOUS_VECTOR_OFFSET 0x000000F0
+#define APIC_REGISTER_ICR_LOW_OFFSET 0x00000300
+#define APIC_REGISTER_ICR_HIGH_OFFSET 0x00000310
+#define APIC_REGISTER_LINT0_VECTOR_OFFSET 0x00000350
+#define APIC_REGISTER_LINT1_VECTOR_OFFSET 0x00000360
+
+#define BROADCAST_MODE_SPECIFY_CPU 0x00
+#define BROADCAST_MODE_ALL_INCLUDING_SELF 0x01
+#define BROADCAST_MODE_ALL_EXCLUDING_SELF 0x02
+
+#ifndef DELIVERY_MODE_FIXED
+#define DELIVERY_MODE_FIXED 0x0
+#endif
+#ifndef DELIVERY_MODE_LOWEST_PRIORITY
+#define DELIVERY_MODE_LOWEST_PRIORITY 0x1
+#endif
+#ifndef DELIVERY_MODE_SMI
+#define DELIVERY_MODE_SMI 0x2
+#endif
+#ifndef DELIVERY_MODE_REMOTE_READ
+#define DELIVERY_MODE_REMOTE_READ 0x3
+#endif
+#ifndef DELIVERY_MODE_NMI
+#define DELIVERY_MODE_NMI 0x4
+#endif
+#ifndef DELIVERY_MODE_INIT
+#define DELIVERY_MODE_INIT 0x5
+#endif
+#ifndef DELIVERY_MODE_SIPI
+#define DELIVERY_MODE_SIPI 0x6
+#endif
+#ifndef DELIVERY_MODE_MAX
+#define DELIVERY_MODE_MAX 0x7
+#endif
+
+#ifndef TRIGGER_MODE_EDGE
+#define TRIGGER_MODE_EDGE 0x00
+#endif
+#ifndef TRIGGER_MODE_LEVEL
+#define TRIGGER_MODE_LEVEL 0x01
+#endif
+
+#ifndef CPU_FEATURE_DISABLE
+#define CPU_FEATURE_DISABLE 0
+#endif
+#ifndef CPU_FEATURE_ENABLE
+#define CPU_FEATURE_ENABLE 1
+#endif
+
+#define CACHE_UNCACHEABLE 0
+#define CACHE_WRITECOMBINING 1
+#define CACHE_WRITETHROUGH 4
+#define CACHE_WRITEPROTECTED 5
+#define CACHE_WRITEBACK 6
+
+
+//
+// Processor Definitions
+//
+#define CPUID_FULL_STEPPING 0x0000000F
+#define CPUID_FULL_FAMILY_MODEL 0x0FFF0FF0
+#define CPUID_FULL_FAMILY_MODEL_STEPPING 0x0FFF0FFF
+#define CPUID_FULL_FAMILY_MODEL_SKYLAKE_ULT_ULX 0x000406E0
+#define CPUID_FULL_FAMILY_MODEL_SKYLAKE_DT_HALO 0x000506E0
+#define CPUID_FULL_FAMILY_MODEL_KABYLAKE_ULT_ULX 0x000806E0
+#define CPUID_FULL_FAMILY_MODEL_KABYLAKE_DT_HALO 0x000906E0
+
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND 1
+#endif
+#ifndef STALL_ONE_MILLI_SECOND
+#define STALL_ONE_MILLI_SECOND 1000
+#endif
+
+#define BITS(x) (1 << (x))
+
+/**
+Notes :
+ 1. Bit position always starts at 0.
+ 2. Following macros are applicable only for Word aligned integers.
+**/
+#define BIT(Pos, Value) (1 << (Pos) & (Value))
+#define BITRANGE(From, Width, Value) (((Value) >> (From)) & ((1 << (Width)) - 1))
+
+///
+/// Enums for CPU Family IDs
+///
+typedef enum {
+ EnumCpuSklUltUlx = CPUID_FULL_FAMILY_MODEL_SKYLAKE_ULT_ULX,
+ EnumCpuSklDtHalo = CPUID_FULL_FAMILY_MODEL_SKYLAKE_DT_HALO,
+ EnumCpuKblUltUlxG0 = EnumCpuSklUltUlx,
+ EnumCpuKblDtHaloA0 = EnumCpuSklDtHalo,
+ EnumCpuKblUltUlx = CPUID_FULL_FAMILY_MODEL_KABYLAKE_ULT_ULX,
+ EnumCpuKblDtHalo = CPUID_FULL_FAMILY_MODEL_KABYLAKE_DT_HALO,
+ EnumCpuMax = CPUID_FULL_FAMILY_MODEL
+} CPU_FAMILY;
+
+///
+/// Enums for CPU Stepping IDs
+///
+typedef enum {
+ ///
+ /// Skylake ULX/ULT Steppings
+ ///
+ EnumSklB0 = 1,
+ EnumSklJ0 = 2,
+ EnumSklC0 = 2,
+ EnumSklK0 = 3,
+ EnumSklD0 = 3,
+ EnumSklMaxUltUlxStep = EnumSklD0,
+
+ ///
+ /// Kabylake ULX/ULT Steppings
+ ///
+ EnumKblG0 = 8,
+ EnumKblH0 = 9,
+ EnumKblJ0 = 9,
+ EnumKblY0 = 0xA,
+ EnumKblMaxUltUlxStep = EnumKblY0,
+
+ ///
+ /// Skylake DT/Halo Steppings
+ ///
+ EnumSklP0 = 0,
+ EnumSklQ0 = 1,
+ EnumSklM0 = 2,
+ EnumSklR0 = 3,
+ EnumSklS0 = 3,
+ EnumSklN0 = 3,
+ EnumSklMaxDtHaloStep = EnumSklN0,
+
+ ///
+ /// Kabylake DT/Halo Steppings
+ ///
+ EnumKblA0 = 8,
+ EnumKblB0 = 9,
+ EnumKblS0 = 9,
+ EnumKblM0 = 9,
+ EnumKblN0 = 0xA,
+ EnumKblMaxDtHaloStep = EnumKblN0,
+
+ ///
+ /// Max Stepping
+ ///
+ EnumCpuSteppingMax = CPUID_FULL_STEPPING
+} CPU_STEPPING;
+
+///
+/// Enums for CPU SKU IDs
+///
+typedef enum {
+ EnumCpuUlt = 0,
+ EnumCpuTrad,
+ EnumCpuUlx,
+ EnumCpuHalo,
+ EnumCpuUnknown
+} CPU_SKU;
+
+///
+/// Enums for CPU Generation
+///
+typedef enum {
+ EnumSklCpu = 0,
+ EnumKblCpu,
+ EnumCpuUnknownGeneration
+} CPU_GENERATION;
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuMailboxLib.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuMailboxLib.h
new file mode 100644
index 0000000000..0c2df2ff80
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuMailboxLib.h
@@ -0,0 +1,96 @@
+/** @file
+ Header file for Cpu Mailbox Lib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CPU_MAILBOX_LIB_H_
+#define _CPU_MAILBOX_LIB_H_
+
+//
+// Mailbox Related Definitions
+//
+
+/**
+ Generic Mailbox function for mailbox write commands. This function will
+ poll the mailbox interface for control, issue the write request, poll
+ for completion, and verify the write was succussful.
+
+ @param[in] MailboxType The type of mailbox interface to read. The Overclocking mailbox is defined as MAILBOX_TYPE_OC = 2.
+ @param[in] MailboxCommand Overclocking mailbox command data
+ @param[in] MailboxData Overclocking mailbox interface data
+ @param[out] *MailboxStatus Pointer to the mailbox status returned from pcode. Possible mailbox status values are:
+ - SUCCESS (0) Command succeeded.
+ - OC_LOCKED (1) Overclocking is locked. Service is read-only.
+ - INVALID_DOMAIN (2) Invalid Domain ID provided in command data.
+ - MAX_RATIO_EXCEEDED (3) Ratio exceeds maximum overclocking limits.
+ - MAX_VOLTAGE_EXCEEDED (4) Voltage exceeds input VR's max voltage.
+ - OC_NOT_SUPPORTED (5) Domain does not support overclocking.
+
+ @retval EFI_STATUS
+ - EFI_SUCCESS Command succeeded.
+ - EFI_INVALID_PARAMETER Invalid read data detected from pcode.
+ - EFI_UNSUPPORTED Unsupported MailboxType parameter.
+**/
+EFI_STATUS
+EFIAPI
+MailboxWrite (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ IN UINT32 MailboxData,
+ OUT UINT32 *MailboxStatus
+ );
+
+/**
+ Generic Mailbox function for mailbox read commands. This function will write
+ the read request from MailboxType, and populate the read results in the MailboxDataPtr.
+
+ @param[in] MailboxType The type of mailbox interface to read. The Overclocking mailbox is defined as MAILBOX_TYPE_OC = 2.
+ @param[in] MailboxCommand Overclocking mailbox command data
+ @param[out] *MailboxDataPtr Pointer to the overclocking mailbox interface data
+ @param[out] *MailboxStatus Pointer to the mailbox status returned from pcode. Possible mailbox status are
+ - SUCCESS (0) Command succeeded.
+ - OC_LOCKED (1) Overclocking is locked. Service is read-only.
+ - INVALID_DOMAIN (2) Invalid Domain ID provided in command data.
+ - MAX_RATIO_EXCEEDED (3) Ratio exceeds maximum overclocking limits.
+ - MAX_VOLTAGE_EXCEEDED (4) Voltage exceeds input VR's max voltage.
+ - OC_NOT_SUPPORTED (5) Domain does not support overclocking.
+
+ @retval EFI_STATUS
+ - EFI_SUCCESS Command succeeded.
+ - EFI_INVALID_PARAMETER Invalid read data detected from pcode.
+ - EFI_UNSUPPORTED Unsupported MailboxType parameter.
+
+**/
+EFI_STATUS
+EFIAPI
+MailboxRead (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ OUT UINT32 *MailboxDataPtr,
+ OUT UINT32 *MailboxStatus
+ );
+
+/**
+ Poll the run/busy bit of the mailbox until available or timeout expires.
+
+ @param[in] MailboxType
+
+ @retval EFI_STATUS
+ - EFI_SUCCESS Command succeeded.
+ - EFI_TIMEOUT Command timeout.
+**/
+EFI_STATUS
+EFIAPI
+PollMailboxReady (
+ IN UINT32 MailboxType
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h
new file mode 100644
index 0000000000..d1ccc5e7fb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h
@@ -0,0 +1,102 @@
+/** @file
+ Header file for CpuPlatform Lib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CPU_PLATFORM_LIB_H_
+#define _CPU_PLATFORM_LIB_H_
+
+#include <CpuRegs.h>
+#include <CpuDataStruct.h>
+
+/**
+ Check CPU Type of the platform
+
+ @retval CPU_FAMILY CPU type
+**/
+CPU_FAMILY
+EFIAPI
+GetCpuFamily (
+ VOID
+ );
+
+/**
+ Return Cpu stepping type
+
+ @retval CPU_STEPPING Cpu stepping type
+**/
+CPU_STEPPING
+EFIAPI
+GetCpuStepping (
+ VOID
+ );
+
+/**
+ Return CPU Sku
+
+ @retval UINT8 CPU Sku
+**/
+UINT8
+EFIAPI
+GetCpuSku (
+ VOID
+ );
+
+
+/**
+ Returns the processor microcode revision of the processor installed in the system.
+
+ @retval Processor Microcode Revision
+**/
+UINT32
+GetCpuUcodeRevision (
+ VOID
+ );
+
+/**
+ Check if this microcode is correct one for processor
+
+ @param[in] Cpuid - processor CPUID
+ @param[in] MicrocodeEntryPoint - entry point of microcode
+ @param[in] Revision - revision of microcode
+
+ @retval CorrectMicrocode if this microcode is correct
+**/
+BOOLEAN
+CheckMicrocode (
+ IN UINT32 Cpuid,
+ IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint,
+ IN UINT32 *Revision
+ );
+
+
+/**
+ Check on the processor if SGX is supported.
+
+ @retval True if SGX supported or FALSE if not
+**/
+BOOLEAN
+IsSgxSupported (
+ VOID
+ );
+
+/**
+ Get processor generation
+
+ @retval EnumSklCpu Executing thread is Skylake
+ @retval EnumKblCpu Executing thread is Kabylake
+**/
+CPU_GENERATION
+GetCpuGeneration (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLib.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLib.h
new file mode 100644
index 0000000000..f05c5743d7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLib.h
@@ -0,0 +1,54 @@
+/** @file
+ Prototype of the CpuPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_POLICY_LIB_H_
+#define _CPU_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+
+/**
+ Print whole CPU config blocks of SiPolicyPpi and serial out.
+
+ @param[in] SiPolicyPpi The SI Policy PPI instance
+**/
+VOID
+CpuPrintPolicy (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ Get CPU config block table total size.
+
+ @retval Size of CPU config block table
+**/
+UINT16
+EFIAPI
+CpuGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ CpuAddConfigBlocks add all Cpu config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add CPU config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CpuAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+#endif // _PEI_CPU_POLICY_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLibPreMem.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLibPreMem.h
new file mode 100644
index 0000000000..905937ec88
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Library/CpuPolicyLibPreMem.h
@@ -0,0 +1,54 @@
+/** @file
+ Prototype of the CpuPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_PREMEM_POLICY_LIB_H_
+#define _CPU_PREMEM_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+
+/**
+ Print whole CPU related config blocks of SI_PREMEM_POLICY_PPI and serial out.
+
+ @param[in] SiPreMemPolicyPpi The Si PreMem Policy PPI instance
+**/
+VOID
+CpuPreMemPrintPolicy (
+IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+);
+
+/**
+ Get CPU PREMEM config block table total size.
+
+ @retval Size of CPU PREMEM config block table
+**/
+UINT16
+EFIAPI
+CpuGetPreMemConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ CpuAddPreMemConfigBlocks add all CPU PREMEM config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add CPU PREMEM config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CpuAddPreMemConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+#endif // _CPU_PREMEM_POLICY_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuGlobalNvsArea.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuGlobalNvsArea.h
new file mode 100644
index 0000000000..6e807a3504
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuGlobalNvsArea.h
@@ -0,0 +1,167 @@
+/** @file
+ Definition of the CPU global NVS area protocol. This protocol
+ publishes the address and format of a global ACPI NVS buffer used as a communications
+ buffer between SMM/DXE/PEI code and ASL code.
+
+ @note Data structures defined in this protocol are not naturally aligned.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_GLOBAL_NVS_AREA_H_
+#define _CPU_GLOBAL_NVS_AREA_H_
+
+typedef struct _CPU_GLOBAL_NVS_AREA_PROTOCOL CPU_GLOBAL_NVS_AREA_PROTOCOL;
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gCpuGlobalNvsAreaProtocolGuid;
+
+//
+// Processor GlobalNvs Revisions
+//
+#define CPU_GLOBAL_NVS_AREA_REVISION 2
+
+#pragma pack(1)
+///
+/// Config TDP level settings.
+///
+typedef struct {
+ UINT16 CtdpPowerLimit1; ///< CTDP Power Limit1
+ UINT16 CtdpPowerLimit2; ///< CTDP Power Limit2
+ UINT8 CtdpPowerLimitWindow; ///< CTDP Power Limit Time Window
+ UINT8 CtdpCtc; ///< CTDP CTC
+ UINT8 CtdpTar; ///< CTDP TAR
+ UINT8 CtdpPpc; ///< CTDP PPC
+} PPM_CTDP_LEVEL_SETTINGS;
+
+///
+/// Global NVS Area definition
+///
+typedef struct {
+ /**
+ This member specifies the revision of the CPU_GLOBAL_NVS_AREA. This field is used to indicate backward
+ compatible changes to the NVS AREA. Any such changes to this PPI will result in an update in the revision number.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ **/
+ UINT8 Revision; ///< (0) CPU GlobalNvs Revision
+ //
+ // PPM Flag Values
+ //
+ UINT32 PpmFlags; ///< (1-4) PPM Flags
+ UINT8 Reserved; ///< (5) Reserved
+ //
+ // Thermal Configuration Values
+ //
+ UINT8 AutoCriticalTripPoint; ///< (6) Auto Critical Trip Point
+ UINT8 AutoPassiveTripPoint; ///< (7) Auto Passive Trip Point
+ UINT8 AutoActiveTripPoint; ///< (8) Auto Active Trip Point
+ UINT32 Cpuid; ///< (9) CPUID
+ //
+ // ConfigTDP Values
+ //
+ UINT8 ConfigurablePpc; ///< (13) Boot Mode vlues for _PPC
+ //
+ // ConfigTDP Level settngs
+ //
+ UINT8 CtdpLevelsSupported; ///< (14) ConfigTdp Number Of Levels
+ UINT8 ConfigTdpBootModeIndex; ///< (15) CTDP Boot Mode Index
+ ///
+ /// (16) CTDP Level 0 Power Limit1
+ /// (18) CTDP Level 0 Power Limit2
+ /// (20) CTDP Level 0 Power Limit1 Time Window
+ /// (21) CTDP Level 0 CTC
+ /// (22) CTDP Level 0 TAR
+ /// (23) CTDP Level 0 PPC
+ /// (24) CTDP Level 1 Power Limit1
+ /// (26) CTDP Level 1 Power Limit2
+ /// (28) CTDP Level 1 Power Limit1 Time Window
+ /// (29) CTDP Level 1 CTC
+ /// (30) CTDP Level 1 TAR
+ /// (31) CTDP Level 1 PPC
+ /// (32) CTDP Level 2 Power Limit1
+ /// (34) CTDP Level 2 Power Limit2
+ /// (36) CTDP Level 2 Power Limit1 Time Window
+ /// (37) CTDP Level 2 CTC
+ /// (38) CTDP Level 2 TAR
+ /// (39) CTDP Level 2 PPC
+ ///
+ PPM_CTDP_LEVEL_SETTINGS CtdpLevelSettings[3];
+ //
+ // Mwait Hints and Latency values for C3/C6/C7/C7S
+ //
+ UINT8 C3MwaitValue; ///< (40) Mwait Hint value for C3
+ UINT8 C6MwaitValue; ///< (41) Mwait Hint value for C6
+ UINT8 C7MwaitValue; ///< (42) Mwait Hint value for C6
+ UINT8 CDMwaitValue; ///< (43) Mwait Hint value for C7/C8/C9/C10
+ UINT16 C3Latency; ///< (44-45) Latency value for C3
+ UINT16 C6Latency; ///< (46-47) Latency Value for C6
+ UINT16 C7Latency; ///< (48-49) Latency Value for C6
+ UINT16 CDLatency; ///< (50-51) Latency Value for C7/C8/C9/C10
+ UINT16 CDIOLevel; ///< (52-53) IO Level Value for C7/C8/C9/C10
+ UINT16 CDPowerValue; ///< (54-55) Power Value for C7/C8/C9/C10
+ UINT8 MiscPowerManagementFlags; ///< (55) MiscPowerManagementFlags
+ //
+ // DTS
+ //
+ UINT8 EnableDigitalThermalSensor; ///< (57) DTS Function enable
+ UINT8 BspDigitalThermalSensorTemperature; ///< (58) Temperature of BSP
+ UINT8 ApDigitalThermalSensorTemperature; ///< (59) Temperature of AP
+ UINT8 DigitalThermalSensorSmiFunction; ///< (60) SMI function call via DTS IO Trap
+ UINT8 PackageDTSTemperature; ///< (61) Package temperature
+ UINT8 IsPackageTempMSRAvailable; ///< (62) Package Temperature MSR available
+ UINT8 Ap2DigitalThermalSensorTemperature; ///< (63) Temperature of the second AP
+ UINT8 Ap3DigitalThermalSensorTemperature; ///< (64) Temperature of the third AP
+ //
+ // BIOS Guard
+ //
+ UINT64 BiosGuardMemAddress; ///< (65-72) BIOS Guard Memory Address for Tool Interface
+ UINT8 BiosGuardMemSize; ///< (73) BIOS Guard Memory Size for Tool Interface
+ UINT16 BiosGuardIoTrapAddress; ///< (74-75) IoTrap Address for Tool Interface
+ UINT16 BiosGuardIoTrapLength; ///< (76-77) IoTrap Length for Tool Interface
+ //
+ // DTS I/O Trap
+ //
+ UINT16 DtsIoTrapAddress; ///< (78-79) DTS IO trap Address
+ UINT8 DtsIoTrapLength; ///< (80) DTS IO trap Length
+ UINT8 DtsAcpiEnable; ///< (81) DTS is in ACPI Mode Enabled
+
+ //
+ // Software Guard Extension
+ //
+ UINT8 SgxStatus; ///< (82) SE Status
+ UINT64 EpcBaseAddress; ///< (83-90) EPC Base Address
+ UINT64 EpcLength; ///< (91-98) EPC Length
+
+ //
+ // HWP
+ //
+ UINT8 HwpVersion; ///< (99) HWP Status
+ UINT16 HwpIoTrapAddress; ///< (100-101) IoTrap Address for HWP
+ UINT16 HwpIoTrapLength; ///< (102-103) IoTrap Length for HWP
+
+ UINT8 PowerState; ///< (104) Power State
+ UINT8 EnableHdcPolicy; ///< (105) Hardware Duty Cycling Policy
+
+ UINT8 HwpInterruptStatus; ///< (106) HWP Interrupt Status
+ UINT8 DtsInterruptStatus; ///< (107) DTS Interrupt Status
+} CPU_GLOBAL_NVS_AREA;
+#pragma pack()
+///
+/// CPU Global NVS Area Protocol
+///
+struct _CPU_GLOBAL_NVS_AREA_PROTOCOL {
+ CPU_GLOBAL_NVS_AREA *Area; ///< CPU NVS Area
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuInfo.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuInfo.h
new file mode 100644
index 0000000000..d59994471d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Include/Protocol/CpuInfo.h
@@ -0,0 +1,128 @@
+/** @file
+ Protocol used to report CPU information
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_INFO_H_
+#define _CPU_INFO_H_
+
+#include <CpuDataStruct.h>
+
+typedef struct _CPU_INFO_PROTOCOL CPU_INFO_PROTOCOL;
+
+
+extern EFI_GUID gCpuInfoProtocolGuid;
+
+//
+// DXE_CPU_INFO_PROTOCOL revisions
+//
+#define CPU_INFO_PROTOCOL_REVISION 1
+
+//
+// Processor feature definitions.
+//
+#define TXT_SUPPORT BIT0
+#define VMX_SUPPORT BIT1
+#define XD_SUPPORT BIT2
+#define DCA_SUPPORT BIT3
+#define X2APIC_SUPPORT BIT4
+#define AES_SUPPORT BIT5
+#define HT_SUPPORT BIT6
+#define DEBUG_SUPPORT BIT7
+#define DEBUG_LOCK_SUPPORT BIT8
+#define PROC_TRACE_SUPPORT BIT9
+#define HDC_SUPPORT BIT10
+
+
+#pragma pack(1)
+///
+/// Cache descriptor information
+///
+typedef struct {
+ UINT8 Desc; ///< Cache Descriptor
+ UINT8 Level; ///< Cache Level
+ UINT8 Type; ///< Cache Type. 0: Data, 1: Instruction, 3: Unified
+ UINT32 Size; ///< Cache Size.
+ UINT16 Associativity; ///< Cache Ways of Associativity.
+} CACHE_DESCRIPTOR_INFO;
+
+///
+/// Processor information
+///
+typedef struct {
+ UINT32 CpuSignature; ///< Processor signature and version information.
+ UINT64 Features; ///< Features availability in the CPU based on reading ECX after doing Asmcpuid(EAX=1).
+ CHAR8 *BrandString; ///< Processor Brand String.
+ UINT8 NumSupportedCores; ///< Total Number of Supported Cores in CPU Package. If Dual core, 2 cores.
+ UINT8 NumSupportedThreadsPerCore; ///< Number of Supported Threads per Core.
+ UINT8 NumCores; ///< Number of Enabled or Active Cores.
+ UINT8 NumHts; ///< Number of Enabled Threads per Core. This will be 1 or 2.
+ UINT32 IntendedFreq; ///< Maximum non turbo ratio in MHz
+ UINT32 ActualFreq; ///< Actual frequency in MHz
+ UINT32 Voltage; ///< Current operating voltage.
+ CACHE_DESCRIPTOR_INFO *CacheInfo; ///< Cache descriptor information.
+ UINT8 MaxCacheSupported; ///< Maximum cache supported.
+ UINT8 SmmbaseSwSmiNumber; ///< Software SMI Number from Smbase.
+ UINT16 NumberOfPStates; ///< Number of P-States.
+} CPU_INFO;
+
+///
+/// This HOB is data structure representing two different address location in SMRAM to hold SMRAM CPU DATA.
+///
+typedef struct {
+ EFI_PHYSICAL_ADDRESS LockBoxData; ///< First location (address) of SMRAM CPU DATA.
+ EFI_PHYSICAL_ADDRESS SmramCpuData; ///< Second location (Address) of SMRAM CPU DATA.
+ UINT64 LockBoxSize; ///< Size of SMRAM CPU DATA.
+} SMRAM_CPU_INFO;
+
+///
+/// SGX Information
+///
+typedef struct {
+ UINT64 SgxSinitNvsData; ///< Sinit SE SVN Version saved and passed back in next boot
+} SGX_INFO;
+
+#pragma pack()
+
+///
+/// This protocol provides information about the common features available in this CPU.
+///
+struct _CPU_INFO_PROTOCOL {
+ /**
+ Revision for the protocol structure.
+ Any backwards compatible changes to this protocol will result in an update in the revision number.
+ Major changes will require publication of a new protocol
+
+ <b>Revision 1</b>:
+ - Initial version
+ **/
+ UINT8 Revision;
+ /**
+ CPU Supported Feature.
+ - BIT0: If set then processor supports TXT.
+ - BIT1: If set then processor supports virtual mode extensions.
+ - BIT2: If set then processor supports execute disable bit.
+ - BIT3: If set then processor supports DCA.
+ - BIT4: If set then processor supports X2APIC.
+ - BIT5: If set then processor supports Advanced Encryption Standard.
+ - BIT6: If set then processor supports hyperthreading.
+ - BIT7: If set then processor supports debug interface.
+ - BIT8: If set then processor supports debug interface lock.
+ - BIT9: If set then processor supports processor trace.
+ - BIT10: If Set then processor supports supports HDC.
+ **/
+ UINT64 CpuCommonFeatures;
+ CPU_INFO *CpuInfo; ///< Processor Basic Information
+ SMRAM_CPU_INFO *SmramCpuInfo; ///< SMRAM CPU Information
+ SGX_INFO *SgxInfo; ///< SGX Information
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuInitDataHob.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuInitDataHob.h
new file mode 100644
index 0000000000..cdc6c463b6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuInitDataHob.h
@@ -0,0 +1,50 @@
+/** @file
+ Struct and GUID definitions for CpuInitDataHob.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_INIT_DATA_HOB_H_
+#define _CPU_INIT_DATA_HOB_H_
+
+#include <Ppi/SiPolicy.h>
+
+extern EFI_GUID gCpuInitDataHobGuid;
+
+#define MAX_PROCESSOR_THREADS 0x40
+
+///
+/// CPU Configuration Structure passed from PEI to DXE phase
+///
+typedef struct {
+ UINT32 ApHandoffManner : 2;
+ UINT32 ApIdleManner : 2;
+ UINT32 EnableDts : 2;
+ UINT32 HdcControl : 2;
+ UINT32 Hwp : 2;
+ UINT32 ConfigTdpBios : 1;
+ UINT32 RsvdBits :21;
+ UINT8 SmmbaseSwSmiNumber;
+ UINT8 Rsvd[3];
+} CPU_CONFIG_DATA;
+
+///
+/// This HOB is used to pass only the required information from PEI for DXE consumption.
+///
+typedef struct {
+ UINT32 Revision;
+ EFI_PHYSICAL_ADDRESS CpuConfigData; ///< CPU RC Config for DXE consumption
+ EFI_PHYSICAL_ADDRESS CpuGnvsPointer; ///< CPU_GLOBAL_NVS_AREA Pointer.
+ EFI_PHYSICAL_ADDRESS MpData; ///< Deprecated. Points to ACPI_CPU_DATA structure with multiprocessor data.
+ EFI_PHYSICAL_ADDRESS FvidTable; ///< FVID Table.
+ UINT32 SiliconInfo; ///< SILICON_INFO data
+} CPU_INIT_DATA_HOB;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuPrivateData.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuPrivateData.h
new file mode 100644
index 0000000000..13ca1f2a01
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/CpuPrivateData.h
@@ -0,0 +1,27 @@
+/** @file
+ Struct definition for CpuPrivateData.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CPU_PRIVATE_DATA_H_
+#define _CPU_PRIVATE_DATA_H_
+
+#include <CpuInitDataHob.h>
+
+///
+/// CPU Private Data saved and restored for S3.
+///
+typedef struct {
+ UINT64 ProcessorTraceAddress[MAX_PROCESSOR_THREADS];
+ UINT32 S3BspMtrrTablePointer;
+} CPU_PRIVATE_DATA;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/Library/CpuCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/Library/CpuCommonLib.h
new file mode 100644
index 0000000000..8099236d88
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/Library/CpuCommonLib.h
@@ -0,0 +1,192 @@
+/** @file
+ Header file for Cpu Common Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CPU_COMMON_LIB_H_
+#define _CPU_COMMON_LIB_H_
+
+typedef UINT32 CPU_RESET_TYPE;
+
+#define NO_RESET 0
+#define WARM_RESET BIT0
+#define COLD_RESET (BIT0 | BIT1)
+
+
+/**
+ Set up flags in CR4 for XMM instruction enabling
+**/
+VOID
+EFIAPI
+XmmInit (
+ VOID
+ );
+
+/**
+ Enable "Machine Check Enable"
+**/
+VOID
+EFIAPI
+EnableMce (
+ VOID
+ );
+
+/**
+ Mtrr Synch Up Entry
+**/
+UINTN
+EFIAPI
+MpMtrrSynchUpEntry (
+ VOID
+ );
+
+/**
+ Mtrr Synch Up Exit
+**/
+VOID
+EFIAPI
+MpMtrrSynchUpExit (
+ UINTN Cr4
+ );
+
+/**
+ This procedure sends an IPI to the designated processor in
+ the requested delivery mode with the requested vector.
+
+ @param[in] ApicID - APIC ID of processor.
+ @param[in] VectorNumber - Vector number.
+ @param[in] DeliveryMode - I/O APIC Interrupt Deliver Modes
+
+ @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
+ @retval EFI_NOT_READY - There was a pending interrupt
+ @retval EFI_SUCCESS - Interrupt sent successfully
+**/
+EFI_STATUS
+EFIAPI
+CpuSendIpi (
+ IN UINT32 ApicID,
+ IN UINTN VectorNumber,
+ IN UINTN DeliveryMode
+ );
+
+
+/**
+ Get APIC ID of processor
+
+ @retval APIC ID of processor
+**/
+UINT32
+GetCpuApicId (
+ VOID
+ );
+
+/**
+ Programs XAPIC registers.
+
+ @param[in] Bsp - Is this BSP?
+**/
+VOID
+ProgramXApic (
+ BOOLEAN Bsp
+ );
+
+/**
+ This function is to disable BIOS Write Protect in SMM phase.
+**/
+VOID
+EFIAPI
+CpuSmmDisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is to enable BIOS Write Protect in SMM phase.
+**/
+VOID
+EFIAPI
+CpuSmmEnableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function returns the maximum number of cores supported in this physical processor package.
+
+ @retval Maximum number of supported cores in the package.
+**/
+UINT8
+GetMaxSupportedCoreCount (
+ VOID
+ );
+
+/**
+ This function returns the actual factory-configured number of threads per core,
+ and actual factory-configured number of cores in this physical processor package.
+
+ @param[out] *ThreadsPerCore - variable that will store Maximum enabled threads per core
+ @param[out] *NumberOfCores - variable that will store Maximum enabled cores per die
+**/
+VOID
+GetSupportedCount (
+ OUT UINT16 *ThreadsPerCore, OPTIONAL
+ OUT UINT16 *NumberOfCores OPTIONAL
+ );
+
+
+/**
+ Check to see if the executing thread is BSP
+
+ @retval TRUE Executing thread is BSP
+ @retval FALSE Executing thread is AP
+**/
+BOOLEAN
+IsBsp (
+ VOID
+ );
+
+
+/**
+ Return TRUE if PRMRR base was already set on this core and was
+ locked
+
+ @retval TRUE PRMRR base was already set
+ @retval FALSE PRMRR base wasn't set
+**/
+BOOLEAN
+IsPrmrrAlreadySet (
+ VOID
+ );
+
+/**
+ Check if this is non-core processor - HT AP thread
+
+ @retval TRUE if this is HT AP thread
+ @retval FALSE if this is core thread
+**/
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ );
+
+
+/**
+ Based on ResetType, perform warm or cold reset using PCH reset PPI.
+
+ @param[in] ResetType - CPU_RESET_TYPE to indicate which reset should be performed.
+
+ @retval EFI_SUCCESS - Function successful (system should already reset).
+ @retval EFI_UNSUPPORTED - Reset type unsupported.
+**/
+EFI_STATUS
+PerformWarmOrColdReset (
+ IN CPU_RESET_TYPE ResetType
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/PowerMgmtNvsStruct.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/PowerMgmtNvsStruct.h
new file mode 100644
index 0000000000..e7f7c19279
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/IncludePrivate/PowerMgmtNvsStruct.h
@@ -0,0 +1,178 @@
+/** @file
+ This file contains CPU Gnvs Struct specific to processor
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _POWER_MGMT_NVS_STRUCT_H_
+#define _POWER_MGMT_NVS_STRUCT_H_
+
+//
+// Processor Power Management GlobalNvs Revisions
+//
+#define CPU_GLOBAL_NVS_AREA_REVISION 2
+
+//
+// Structure Declarations
+//
+#pragma pack(1)
+///
+/// Config TDP level settings.
+///
+typedef struct {
+ UINT16 CtdpPowerLimit1; ///< CTDP Power Limit1
+ UINT16 CtdpPowerLimit2; ///< CTDP Power Limit2
+ UINT8 CtdpPowerLimitWindow; ///< CTDP Power Limit Time Window
+ UINT8 CtdpCtc; ///< CTDP CTC
+ UINT8 CtdpTar; ///< CTDP TAR
+ UINT8 CtdpPpc; ///< CTDP PPC
+} CTDP_LEVEL_SETTINGS;
+
+///
+/// CPU Global NVS Area definition
+///
+typedef struct {
+ /**
+ This member specifies the revision of the CPU_GLOBAL_NVS_AREA. This field is used to indicate backward
+ compatible changes to the NVS AREA. Any such changes to this PPI will result in an update in the revision number.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ **/
+ UINT8 Revision; ///< (0) CPU GlobalNvs Revision
+ //
+ // PPM Flag Values
+ //
+ UINT32 PpmFlags; ///< (1-4) PPM Flags
+ UINT8 Reserved; ///< (5) Reserved
+ //
+ // Thermal Configuration Values
+ //
+ UINT8 AutoCriticalTripPoint; ///< (6) Auto Critical Trip Point
+ UINT8 AutoPassiveTripPoint; ///< (7) Auto Passive Trip Point
+ UINT8 AutoActiveTripPoint; ///< (8) Auto Active Trip Point
+ UINT32 Cpuid; ///< (9) CPUID
+ //
+ // ConfigTDP Values
+ //
+ UINT8 ConfigurablePpc; ///< (13) Boot Mode vlues for _PPC
+ //
+ // ConfigTDP Level settngs
+ //
+ UINT8 CtdpLevelsSupported; ///< (14) ConfigTdp Number Of Levels
+ UINT8 ConfigTdpBootModeIndex; ///< (15) CTDP Boot Mode Index
+ ///
+ /// (16) CTDP Level 0 Power Limit1
+ /// (18) CTDP Level 0 Power Limit2
+ /// (20) CTDP Level 0 Power Limit1 Time Window
+ /// (21) CTDP Level 0 CTC
+ /// (22) CTDP Level 0 TAR
+ /// (23) CTDP Level 0 PPC
+ /// (24) CTDP Level 1 Power Limit1
+ /// (26) CTDP Level 1 Power Limit2
+ /// (28) CTDP Level 1 Power Limit1 Time Window
+ /// (29) CTDP Level 1 CTC
+ /// (30) CTDP Level 1 TAR
+ /// (31) CTDP Level 1 PPC
+ /// (32) CTDP Level 2 Power Limit1
+ /// (34) CTDP Level 2 Power Limit2
+ /// (36) CTDP Level 2 Power Limit1 Time Window
+ /// (37) CTDP Level 2 CTC
+ /// (38) CTDP Level 2 TAR
+ /// (39) CTDP Level 2 PPC
+ ///
+ CTDP_LEVEL_SETTINGS CtdpLevelSettings[3];
+ //
+ // Mwait Hints and Latency values for C3/C6/C7/C7S
+ //
+ UINT8 C3MwaitValue; ///< (40) Mwait Hint value for C3
+ UINT8 C6MwaitValue; ///< (41) Mwait Hint value for C6
+ UINT8 C7MwaitValue; ///< (42) Mwait Hint value for C6
+ UINT8 CDMwaitValue; ///< (43) Mwait Hint value for C7/C8/C9/C10
+ UINT16 C3Latency; ///< (44-45) Latency value for C3
+ UINT16 C6Latency; ///< (46-47) Latency Value for C6
+ UINT16 C7Latency; ///< (48-49) Latency Value for C6
+ UINT16 CDLatency; ///< (50-51) Latency Value for C7/C8/C9/C10
+ UINT16 CDIOLevel; ///< (52-53) IO Level Value for C7/C8/C9/C10
+ UINT16 CDPowerValue; ///< (54-55) Power Value for C7/C8/C9/C10
+ UINT8 MiscPowerManagementFlags; ///< (55) MiscPowerManagementFlags
+ //
+ // DTS
+ //
+ UINT8 EnableDigitalThermalSensor; ///< (57) DTS Function enable
+ UINT8 BspDigitalThermalSensorTemperature; ///< (58) Temperature of BSP
+ UINT8 ApDigitalThermalSensorTemperature; ///< (59) Temperature of AP
+ UINT8 DigitalThermalSensorSmiFunction; ///< (60) SMI function call via DTS IO Trap
+ UINT8 PackageDTSTemperature; ///< (61) Package temperature
+ UINT8 IsPackageTempMSRAvailable; ///< (62) Package Temperature MSR available
+ UINT8 Ap2DigitalThermalSensorTemperature; ///< (63) Temperature of the second AP
+ UINT8 Ap3DigitalThermalSensorTemperature; ///< (64) Temperature of the third AP
+ //
+ // BIOS Guard
+ //
+ UINT64 BiosGuardMemAddress; ///< (65-72) BIOS Guard Memory Address for Tool Interface
+ UINT8 BiosGuardMemSize; ///< (73) BIOS Guard Memory Size for Tool Interface
+ UINT16 BiosGuardIoTrapAddress; ///< (74-75) IoTrap Address for Tool Interface
+ UINT16 BiosGuardIoTrapLength; ///< (76-77) IoTrap Length for Tool Interface
+ //
+ // DTS I/O Trap
+ //
+ UINT16 DtsIoTrapAddress; ///< (78-79) DTS IO trap Address
+ UINT8 DtsIoTrapLength; ///< (80) DTS IO trap Length
+ UINT8 DtsAcpiEnable; ///< (81) DTS is in ACPI Mode Enabled
+
+ //
+ // Software Guard Extension
+ //
+ UINT8 SgxStatus; ///< (82) SE Status
+ UINT64 EpcBaseAddress; ///< (83-90) EPC Base Address
+ UINT64 EpcLength; ///< (91-98) EPC Length
+
+ //
+ // HWP
+ //
+ UINT8 HwpVersion; ///< (99) HWP Status
+ UINT16 HwpIoTrapAddress; ///< (100-101) IoTrap Address for HWP
+ UINT16 HwpIoTrapLength; ///< (102-103) IoTrap Length for HWP
+
+ UINT8 PowerState; ///< (104) Power State
+ UINT8 EnableHdcPolicy; ///< (105) Hardware Duty Cycling Policy
+
+ UINT8 HwpInterruptStatus; ///< (106) HWP Interrupt Status
+ UINT8 DtsInterruptStatus; ///< (107) DTS Interrupt Status
+} CPU_GLOBAL_NVS;
+#pragma pack()
+
+typedef struct _CPU_GLOBAL_NVS_AREA_CONFIG {
+ CPU_GLOBAL_NVS *Area;
+} CPU_GLOBAL_NVS_AREA_CONFIG;
+
+typedef struct _FVID_HEADER {
+ UINT32 Stepping; ///< Matches value returned by CPUID function 1
+ UINT16 MaxBusRatio; ///< Matches BUS_RATIO_MAX field in PERF_STS_MSR
+ UINT16 EistStates; ///< Number of states of FVID (N)
+} FVID_HEADER;
+
+typedef struct _FVID_STATE {
+ UINT32 State; ///< State Number (0 - N-1)
+ UINT16 BusRatio; ///< BUS_RATIO_SEL value to be written to PERF_CTL
+ UINT32 Power; ///< Typical power consumed by CPU in this state
+ UINT32 Limit16State; ///< State Number (0 - N-1) with limit 16 P-states
+ UINT16 Limit16BusRatio; ///< BUS_RATIO_SEL value to be written to PERF_CTL with limit 16 P-states
+ UINT32 Limit16Power; ///< Typical power consumed by CPU in this state with limit 16 P-states
+} FVID_STATE;
+
+typedef union _FVID_TABLE {
+ FVID_HEADER FvidHeader;
+ FVID_STATE FvidState;
+ UINT64 FvidData;
+} FVID_TABLE;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.c b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.c
new file mode 100644
index 0000000000..ed964d00c3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.c
@@ -0,0 +1,95 @@
+/** @file
+ Mailbox Library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+
+/**
+ Generic Mailbox function for mailbox write commands. This function will
+ poll the mailbox interface for control, issue the write request, poll
+ for completion, and verify the write was successful.
+
+ @param[in] MailboxType The type of mailbox interface to read. The Overclocking mailbox is defined as MAILBOX_TYPE_OC = 2.
+ @param[in] MailboxCommand Overclocking mailbox command data
+ @param[in] MailboxData Overclocking mailbox interface data
+ @param[out] *MailboxStatus Pointer to the mailbox status returned from pcode. Possible mailbox status values are:
+ - SUCCESS (0) Command succeeded.
+ - OC_LOCKED (1) Overclocking is locked. Service is read-only.
+ - INVALID_DOMAIN (2) Invalid Domain ID provided in command data.
+ - MAX_RATIO_EXCEEDED (3) Ratio exceeds maximum overclocking limits.
+ - MAX_VOLTAGE_EXCEEDED (4) Voltage exceeds input VR's max voltage.
+ - OC_NOT_SUPPORTED (5) Domain does not support overclocking.
+
+ @retval EFI_SUCCESS Command succeeded.
+ @retval EFI_INVALID_PARAMETER Invalid read data detected from pcode.
+ @retval EFI_UNSUPPORTED Unsupported MailboxType parameter.
+**/
+EFI_STATUS
+EFIAPI
+MailboxWrite (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ IN UINT32 MailboxData,
+ OUT UINT32 *MailboxStatus
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Generic Mailbox function for mailbox read commands. This function will write
+ the read request from MailboxType, and populate the read results in the MailboxDataPtr.
+
+ @param[in] MailboxType The type of mailbox interface to read. The Overclocking mailbox is defined as MAILBOX_TYPE_OC = 2.
+ @param[in] MailboxCommand Overclocking mailbox command data
+ @param[out] *MailboxDataPtr Pointer to the overclocking mailbox interface data
+ @param[out] *MailboxStatus Pointer to the mailbox status returned from pcode. Possible mailbox status are
+ - SUCCESS (0) Command succeeded.
+ - OC_LOCKED (1) Overclocking is locked. Service is read-only.
+ - INVALID_DOMAIN (2) Invalid Domain ID provided in command data.
+ - MAX_RATIO_EXCEEDED (3) Ratio exceeds maximum overclocking limits.
+ - MAX_VOLTAGE_EXCEEDED (4) Voltage exceeds input VR's max voltage.
+ - OC_NOT_SUPPORTED (5) Domain does not support overclocking.
+
+ @retval EFI_SUCCESS Command succeeded.
+ @retval EFI_INVALID_PARAMETER Invalid read data detected from pcode.
+ @retval EFI_UNSUPPORTED Unsupported MailboxType parameter.
+**/
+EFI_STATUS
+EFIAPI
+MailboxRead (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ OUT UINT32 *MailboxDataPtr,
+ OUT UINT32 *MailboxStatus
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Poll the run/busy bit of the mailbox until available or timeout expires.
+
+ @param[in] MailboxType
+
+ @retval EFI_SUCCESS Command succeeded.
+ @retval EFI_TIMEOUT Command timeout.
+**/
+EFI_STATUS
+EFIAPI
+PollMailboxReady (
+ IN UINT32 MailboxType
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.inf b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.inf
new file mode 100644
index 0000000000..0426e05802
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.inf
@@ -0,0 +1,29 @@
+## @file
+# Component description file for Cpu Mailbox Null Lib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseCpuMailboxLibNull
+FILE_GUID = 74F470BC-1769-4732-B9C0-EE9AB0B12411
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = CpuMailboxLib
+
+[Packages]
+MdePkg/MdePkg.dec
+
+[Sources]
+BaseCpuMailboxLibNull.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/CpuPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/CpuPrintPolicy.c
new file mode 100644
index 0000000000..f871c21e6a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/CpuPrintPolicy.c
@@ -0,0 +1,286 @@
+/** @file
+ This file is PeiCpuPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiCpuPolicyLibrary.h"
+#include <Library/ConfigBlockLib.h>
+
+/**
+ Print CPU_CONFIG and serial out.
+
+ @param[in] CpuConfig Pointer to a CPU_CONFIG
+**/
+VOID
+CpuConfigPrint (
+ IN CONST CPU_CONFIG *CpuConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ CPU Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " CPU_CONFIG : AesEnable : 0x%x\n", CpuConfig->AesEnable));
+ DEBUG ((DEBUG_INFO, " CPU_CONFIG : EnableRsr : 0x%X\n", CpuConfig->EnableRsr));
+ DEBUG ((DEBUG_INFO, " CPU_CONFIG : EnableDts : 0x%x\n", CpuConfig->EnableDts));
+ DEBUG ((DEBUG_INFO, " CPU_CONFIG : SmmbaseSwSmiNumber : 0x%x\n", CpuConfig->SmmbaseSwSmiNumber));
+ DEBUG ((DEBUG_INFO, " CPU_CONFIG : TxtEnable : 0x%X\n", CpuConfig->TxtEnable));
+ DEBUG ((DEBUG_INFO, " CPU_CONFIG : MicrocodePatchAddress : 0x%x\n", CpuConfig->MicrocodePatchAddress));
+}
+
+
+/**
+ Print CPU_POWER_MGMT_BASIC_CONFIG and serial out.
+
+ @param[in] CpuPowerMgmtBasicConfig Pointer to a CPU_POWER_MGMT_BASIC_CONFIG
+**/
+VOID
+CpuPowerMgmtBasicConfigPrint (
+ IN CONST CPU_POWER_MGMT_BASIC_CONFIG *CpuPowerMgmtBasicConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ CPU Power Mgmt Basic Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG : OneCoreRatioLimit : 0x%X , TwoCoreRatioLimit = 0x%X , ThreeCoreRatioLimit = 0x%X , FourCoreRatioLimit = 0x%X \n", CpuPowerMgmtBasicConfig->OneCoreRatioLimit, \
+ CpuPowerMgmtBasicConfig->TwoCoreRatioLimit, \
+ CpuPowerMgmtBasicConfig->ThreeCoreRatioLimit, \
+ CpuPowerMgmtBasicConfig->FourCoreRatioLimit, \
+ CpuPowerMgmtBasicConfig->FiveCoreRatioLimit, \
+ CpuPowerMgmtBasicConfig->SixCoreRatioLimit, \
+ CpuPowerMgmtBasicConfig->SevenCoreRatioLimit, \
+ CpuPowerMgmtBasicConfig->EightCoreRatioLimit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: Hwp : 0x%x\n", CpuPowerMgmtBasicConfig->Hwp));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: SkipSetBootPState : 0x%x\n", CpuPowerMgmtBasicConfig->SkipSetBootPState));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: HdcControl : 0x%X\n", CpuPowerMgmtBasicConfig->HdcControl));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit2 : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit2));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: TurboPowerLimitLock : 0x%x\n", CpuPowerMgmtBasicConfig->TurboPowerLimitLock));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit3DutyCycle : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit3DutyCycle));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit3Lock : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit3Lock));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit4Lock : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit4Lock));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: TccOffsetClamp : 0x%X\n", CpuPowerMgmtBasicConfig->TccOffsetClamp));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: TccOffsetLock : 0x%X\n", CpuPowerMgmtBasicConfig->TccOffsetLock));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: TurboMode : 0x%x\n", CpuPowerMgmtBasicConfig->TurboMode));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: TccActivationOffset : 0x%X\n", CpuPowerMgmtBasicConfig->TccActivationOffset));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit1 : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit1));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit2Power : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit2Power));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit3 : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit3));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit4 : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit4));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit1Time : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit1Time));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: PowerLimit3Time : 0x%x\n", CpuPowerMgmtBasicConfig->PowerLimit3Time));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_BASIC_CONFIG: TccOffsetTimeWindowForRatl : 0x%X\n", CpuPowerMgmtBasicConfig->TccOffsetTimeWindowForRatl));
+}
+
+/**
+ Print CPU_POWER_MGMT_CUSTOM_CONFIG and serial out.
+
+ @param[in] CpuPowerMgmtCustomConfig Pointer to a CPU_POWER_MGMT_CUSTOM_CONFIG
+**/
+VOID
+CpuPowerMgmtCustomConfigPrint (
+ IN CONST CPU_POWER_MGMT_CUSTOM_CONFIG *CpuPowerMgmtCustomConfig
+ )
+{
+ UINT32 Index = 0;
+ DEBUG ((DEBUG_INFO, "------------------ CPU Power Mgmt Custom Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "\n CustomRatioTable... \n"));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_CUSTOM_CONFIG: VidNumber : 0x%x\n", CpuPowerMgmtCustomConfig->CustomRatioTable.NumberOfEntries));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_CUSTOM_CONFIG: VidCpuid : 0x%x\n", CpuPowerMgmtCustomConfig->CustomRatioTable.Cpuid));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_CUSTOM_CONFIG: VidMaxRatio : 0x%x\n", CpuPowerMgmtCustomConfig->CustomRatioTable.MaxRatio));
+ for (Index = 0; Index < MAX_CUSTOM_RATIO_TABLE_ENTRIES; Index++) {
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_CUSTOM_CONFIG: StateRatio[%d] : 0x%x\n", Index, CpuPowerMgmtCustomConfig->CustomRatioTable.StateRatio[Index]));
+ }
+ for (Index = 0; Index < MAX_CUSTOM_CTDP_ENTRIES; Index++) {
+ DEBUG (
+ (DEBUG_INFO,
+ " CPU_POWER_MGMT_CUSTOM_CONFIG: CustomConfigTdpTable[%d] CustomPowerLimit1 : 0x%x\n",
+ Index,CpuPowerMgmtCustomConfig->CustomConfigTdpTable[Index].CustomPowerLimit1)
+ );
+ DEBUG (
+ (DEBUG_INFO,
+ " CPU_POWER_MGMT_CUSTOM_CONFIG: CustomConfigTdpTable[%d] CustomPowerLimit2 : 0x%x\n",
+ Index,CpuPowerMgmtCustomConfig->CustomConfigTdpTable[Index].CustomPowerLimit2)
+ );
+ DEBUG (
+ (DEBUG_INFO,
+ " CPU_POWER_MGMT_CUSTOM_CONFIG: CustomConfigTdpTable[%d] CustomPowerLimit1Time : 0x%x\n",
+ Index,CpuPowerMgmtCustomConfig->CustomConfigTdpTable[Index].CustomPowerLimit1Time)
+ );
+ DEBUG (
+ (DEBUG_INFO,
+ " CPU_POWER_MGMT_CUSTOM_CONFIG: CustomConfigTdpTable[%d] CustomTurboActivationRatio : 0x%x\n",
+ Index,CpuPowerMgmtCustomConfig->CustomConfigTdpTable[Index].CustomTurboActivationRatio)
+ );
+ }
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_CUSTOM_CONFIG: ConfigTdpLock : 0x%x\n", CpuPowerMgmtCustomConfig->ConfigTdpLock));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_CUSTOM_CONFIG: ConfigTdpBios : 0x%x\n", CpuPowerMgmtCustomConfig->ConfigTdpBios));
+}
+
+/**
+ Print CPU_TEST_CONFIG and serial out.
+
+ @param[in] CpuTestConfig Pointer to a CPU_TEST_CONFIG
+**/
+VOID
+CpuTestConfigPrint (
+ IN CONST CPU_TEST_CONFIG *CpuTestConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ CPU Test Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: MlcStreamerPrefetcher : 0x%X\n", CpuTestConfig->MlcStreamerPrefetcher));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: MlcSpatialPrefetcher : 0x%X\n", CpuTestConfig->MlcSpatialPrefetcher));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: MonitorMwaitEnable : 0x%X\n", CpuTestConfig->MonitorMwaitEnable));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: MachineCheckEnable : 0x%X\n", CpuTestConfig->MachineCheckEnable));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: DebugInterfaceEnable : 0x%X\n", CpuTestConfig->DebugInterfaceEnable));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: DebugInterfaceLockEnable : 0x%X\n", CpuTestConfig->DebugInterfaceLockEnable));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: ApIdleManner: 0x%X\n", CpuTestConfig->ApIdleManner));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: ApHandoffManner: 0x%X\n", CpuTestConfig->ApHandoffManner));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: ProcTraceOutputScheme : 0x%X\n", CpuTestConfig->ProcTraceOutputScheme));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: ProcTraceEnable : 0x%X\n", CpuTestConfig->ProcTraceEnable));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: ProcTraceMemSize : 0x%X\n", CpuTestConfig->ProcTraceMemSize));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: ThreeStrikeCounterDisable : 0x%X\n", CpuTestConfig->ThreeStrikeCounterDisable));
+ DEBUG ((DEBUG_INFO, " CPU_TEST_CONFIG: VoltageOptimization : 0x%X\n", CpuTestConfig->VoltageOptimization));
+}
+
+/**
+ Print CPU_PID_TEST_CONFIG and serial out.
+
+ @param[in] CpuPidTestConfig Pointer to a CPU_PID_TEST_CONFIG
+**/
+VOID
+CpuPidTestConfigPrint (
+ IN CONST CPU_PID_TEST_CONFIG *CpuPidTestConfig
+ )
+{
+ UINT32 Index = 0;
+ DEBUG ((DEBUG_INFO, "------------------ CPU PID Test Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PidTuning : 0x%X\n", Index, CpuPidTestConfig->PidTuning));
+ if ( CpuPidTestConfig->PidTuning == 1) {
+ for (Index = PID_DOMAIN_KP; Index <= PID_DOMAIN_KD; Index++) {
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : Ratl[%X] : 0x%X\n", Index, CpuPidTestConfig->Ratl[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : VrTdcVr0[%X] : 0x%X\n", Index, CpuPidTestConfig->VrTdcVr0[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : VrTdcVr1[%X] : 0x%X\n", Index, CpuPidTestConfig->VrTdcVr1[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : VrTdcVr2[%X] : 0x%X\n", Index, CpuPidTestConfig->VrTdcVr2[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : VrTdcVr3[%X] : 0x%X\n", Index, CpuPidTestConfig->VrTdcVr3[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPsysPl1Msr[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPsysPl1Msr[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPsysPl1MmioPcs[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPsysPl1MmioPcs[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPsysPl2Msr[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPsysPl2Msr[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPsysPl2MmioPcs[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPsysPl2MmioPcs[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPkgPl1Msr[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPkgPl1Msr[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPkgPl1MmioPcs[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPkgPl1MmioPcs[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPkgPl2Msr[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPkgPl2Msr[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : PbmPkgPl2MmioPcs[%X] : 0x%X\n", Index, CpuPidTestConfig->PbmPkgPl2MmioPcs[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : DdrPl1Msr[%X] : 0x%X\n", Index, CpuPidTestConfig->DdrPl1Msr[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : DdrPl1MmioPcs[%X] : 0x%X\n", Index, CpuPidTestConfig->DdrPl1MmioPcs[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : DdrPl2Msr[%X] : 0x%X\n", Index, CpuPidTestConfig->DdrPl2Msr[Index]));
+ DEBUG ((DEBUG_INFO, " CPU_PID_TEST_CONFIG : DdrPl2MmioPcs[%X] : 0x%X\n", Index, CpuPidTestConfig->DdrPl2MmioPcs[Index]));
+ }
+ }
+}
+
+/**
+ Print CPU_POWER_MGMT_TEST_CONFIG and serial out.
+
+ @param[in] CpuPowerMgmtTestConfig Pointer to a CPU_POWER_MGMT_TEST_CONFIG
+**/
+VOID
+CpuPowerMgmtTestConfigPrint (
+ IN CONST CPU_POWER_MGMT_TEST_CONFIG *CpuPowerMgmtTestConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ CPU Power Mgmt Test Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: Eist : 0x%x\n", CpuPowerMgmtTestConfig->Eist));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: EnergyEfficientPState : 0x%x\n", CpuPowerMgmtTestConfig->EnergyEfficientPState));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: EnergyEfficientTurbo : 0x%x\n", CpuPowerMgmtTestConfig->EnergyEfficientTurbo));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: TStates : 0x%x\n", CpuPowerMgmtTestConfig->TStates));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: BiProcHot : 0x%x\n", CpuPowerMgmtTestConfig->BiProcHot));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: DisableProcHotOut : 0x%x\n", CpuPowerMgmtTestConfig->DisableProcHotOut));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: ProcHotResponse : 0x%x\n", CpuPowerMgmtTestConfig->ProcHotResponse));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: DisableVrThermalAlert : 0x%x\n", CpuPowerMgmtTestConfig->DisableVrThermalAlert));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: AutoThermalReporting : 0x%x\n", CpuPowerMgmtTestConfig->AutoThermalReporting));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: ThermalMonitor : 0x%x\n", CpuPowerMgmtTestConfig->ThermalMonitor));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: Cx : 0x%x\n", CpuPowerMgmtTestConfig->Cx));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: PmgCstCfgCtrlLock : 0x%x\n", CpuPowerMgmtTestConfig->PmgCstCfgCtrlLock));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: C1e : 0x%x\n", CpuPowerMgmtTestConfig->C1e));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: C1Autodemotion : 0x%x\n", CpuPowerMgmtTestConfig->C1AutoDemotion));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: C1Undemotion : 0x%x\n", CpuPowerMgmtTestConfig->C1UnDemotion));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: C3AutoDemotion : 0x%x\n", CpuPowerMgmtTestConfig->C3AutoDemotion));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: C3UnDemotion : 0x%x\n", CpuPowerMgmtTestConfig->C3UnDemotion));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: PkgCState Demotion : 0x%x\n", CpuPowerMgmtTestConfig->PkgCStateDemotion));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: PkgCstateUndemotion : 0x%x\n", CpuPowerMgmtTestConfig->PkgCStateUnDemotion));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CStatePreWake : 0x%x\n", CpuPowerMgmtTestConfig->CStatePreWake));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: TimedMwait : 0x%x\n", CpuPowerMgmtTestConfig->TimedMwait));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstCfgCtrIoMwaitRedirection : 0x%x\n", CpuPowerMgmtTestConfig->CstCfgCtrIoMwaitRedirection));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: ProcHotLock : 0x%x\n", CpuPowerMgmtTestConfig->ProcHotLock));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: ConfigTdpLevel : 0x%x\n", CpuPowerMgmtTestConfig->ConfigTdpLevel));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: RaceToHalt : 0x%x\n", CpuPowerMgmtTestConfig->RaceToHalt));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl0Irtl : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl0Irtl));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl1Irtl : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl1Irtl));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl2Irtl : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl2Irtl));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl3Irtl : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl3Irtl));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl4Irtl : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl4Irtl));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl5Irtl : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl5Irtl));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: PkgCStateLimit : 0x%x\n", CpuPowerMgmtTestConfig->PkgCStateLimit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl0TimeUnit : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl0TimeUnit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl1TimeUnit : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl1TimeUnit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl2TimeUnit : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl2TimeUnit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl3TimeUnit : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl3TimeUnit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl4TimeUnit : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl4TimeUnit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CstateLatencyControl5TimeUnit : 0x%x\n", CpuPowerMgmtTestConfig->CstateLatencyControl5TimeUnit));
+ DEBUG ((DEBUG_INFO, " CPU_POWER_MGMT_TEST_CONFIG: CustomPowerUnit : 0x%x\n", CpuPowerMgmtTestConfig->CustomPowerUnit));
+ DEBUG ((DEBUG_INFO, " PpmIrmSetting : 0x%x\n", CpuPowerMgmtTestConfig->PpmIrmSetting));
+}
+/**
+ Print whole CPU config blocks of SI_POLICY_PPI and serial out in PostMem.
+
+ @param[in] SiPolicyPpi The SI Policy PPI instance
+**/
+VOID
+CpuPrintPolicy (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+DEBUG_CODE_BEGIN();
+ EFI_STATUS Status;
+ CPU_CONFIG *CpuConfig;
+ CPU_POWER_MGMT_BASIC_CONFIG *CpuPowerMgmtBasicConfig;
+ CPU_POWER_MGMT_CUSTOM_CONFIG *CpuPowerMgmtCustomConfig;
+ CPU_TEST_CONFIG *CpuTestConfig;
+ CPU_PID_TEST_CONFIG *CpuPidTestConfig;
+ CPU_POWER_MGMT_TEST_CONFIG *CpuPowerMgmtTestConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuConfigGuid, (VOID *) &CpuConfig);
+ ASSERT_EFI_ERROR (Status);
+
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtBasicConfigGuid, (VOID *) &CpuPowerMgmtBasicConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtCustomConfigGuid, (VOID *) &CpuPowerMgmtCustomConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuTestConfigGuid, (VOID *) &CpuTestConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPidTestConfigGuid, (VOID *) &CpuPidTestConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtTestConfigGuid, (VOID *) &CpuPowerMgmtTestConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "\n ------------------------ SiCpuPolicy Print Begin in PostMem----------------- \n"));
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPolicyPpi->TableHeader.Header.Revision));
+
+ CpuConfigPrint(CpuConfig);
+ CpuPowerMgmtBasicConfigPrint(CpuPowerMgmtBasicConfig);
+ CpuPowerMgmtCustomConfigPrint(CpuPowerMgmtCustomConfig);
+ CpuTestConfigPrint(CpuTestConfig);
+ CpuPidTestConfigPrint(CpuPidTestConfig);
+ CpuPowerMgmtTestConfigPrint(CpuPowerMgmtTestConfig);
+ DEBUG ((DEBUG_INFO, "\n ------------------------ SiCpuPolicy Print End in PostMem ----------------- \n\n"));
+DEBUG_CODE_END();
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.c
new file mode 100644
index 0000000000..49331f1471
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.c
@@ -0,0 +1,430 @@
+/** @file
+ This file is PeiCpuPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiCpuPolicyLibrary.h"
+#include <SaAccess.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/MmPciLib.h>
+#include <Library/SaPlatformLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PostCodeLib.h>
+
+#ifndef FSP_FLAG
+/**
+ Get the next microcode patch pointer.
+
+ @param[in, out] MicrocodeData - Input is a pointer to the last microcode patch address found,
+ and output points to the next patch address found.
+
+ @retval EFI_SUCCESS - Patch found.
+ @retval EFI_NOT_FOUND - Patch not found.
+**/
+EFI_STATUS
+EFIAPI
+RetrieveMicrocode (
+ IN OUT CPU_MICROCODE_HEADER **MicrocodeData
+ )
+{
+ UINTN MicrocodeStart;
+ UINTN MicrocodeEnd;
+ UINTN TotalSize;
+
+ if ((FixedPcdGet32 (PcdFlashMicrocodeFvBase) == 0) || (FixedPcdGet32 (PcdFlashMicrocodeFvSize) == 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ///
+ /// Microcode binary in SEC
+ ///
+ MicrocodeStart = (UINTN) FixedPcdGet32 (PcdFlashMicrocodeFvBase) +
+ ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FixedPcdGet32 (PcdFlashMicrocodeFvBase))->HeaderLength +
+ sizeof (EFI_FFS_FILE_HEADER);
+
+ MicrocodeEnd = (UINTN) FixedPcdGet32 (PcdFlashMicrocodeFvBase) + (UINTN) FixedPcdGet32 (PcdFlashMicrocodeFvSize);
+
+ if (*MicrocodeData == NULL) {
+ *MicrocodeData = (CPU_MICROCODE_HEADER *) (UINTN) MicrocodeStart;
+ } else {
+ if (*MicrocodeData < (CPU_MICROCODE_HEADER *) (UINTN) MicrocodeStart) {
+ DEBUG ((DEBUG_INFO, "[CpuPolicy]*MicrocodeData < MicrocodeStart \n"));
+ return EFI_NOT_FOUND;
+ }
+
+ TotalSize = (UINTN) ((*MicrocodeData)->TotalSize);
+ if (TotalSize == 0) {
+ TotalSize = 2048;
+ }
+
+ *MicrocodeData = (CPU_MICROCODE_HEADER *) ((UINTN)*MicrocodeData + TotalSize);
+ if (*MicrocodeData >= (CPU_MICROCODE_HEADER *) (UINTN) (MicrocodeEnd) || (*MicrocodeData)->TotalSize == (UINT32) -1) {
+ DEBUG ((DEBUG_INFO, "[CpuPolicy]*MicrocodeData >= MicrocodeEnd \n"));
+ return EFI_NOT_FOUND;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the microcode patch pointer.
+
+ @retval EFI_PHYSICAL_ADDRESS - Address of the microcode patch, or NULL if not found.
+**/
+EFI_PHYSICAL_ADDRESS
+PlatformCpuLocateMicrocodePatch (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CPU_MICROCODE_HEADER *MicrocodeData;
+ EFI_CPUID_REGISTER Cpuid;
+ UINT32 UcodeRevision;
+ UINTN MicrocodeBufferSize;
+ VOID *MicrocodeBuffer = NULL;
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &Cpuid.RegEax,
+ &Cpuid.RegEbx,
+ &Cpuid.RegEcx,
+ &Cpuid.RegEdx
+ );
+
+ UcodeRevision = GetCpuUcodeRevision ();
+ MicrocodeData = NULL;
+ while (TRUE) {
+ ///
+ /// Find the next patch address
+ ///
+ Status = RetrieveMicrocode (&MicrocodeData);
+ DEBUG ((DEBUG_INFO, "MicrocodeData = %x\n", MicrocodeData));
+
+ if (Status != EFI_SUCCESS) {
+ break;
+ } else if (CheckMicrocode (Cpuid.RegEax, MicrocodeData, &UcodeRevision)) {
+ break;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ return (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
+ }
+
+ ///
+ /// Check that microcode patch size is <= 128K max size,
+ /// then copy the patch from FV to temp buffer for faster access.
+ ///
+ MicrocodeBufferSize = (UINTN) MicrocodeData->TotalSize;
+
+ if (MicrocodeBufferSize <= MAX_MICROCODE_PATCH_SIZE) {
+ MicrocodeBuffer = AllocatePages (EFI_SIZE_TO_PAGES (MicrocodeBufferSize));
+ if (MicrocodeBuffer != NULL) {
+ DEBUG(( DEBUG_INFO, "Copying Microcode to temp buffer.\n"));
+ CopyMem (MicrocodeBuffer, MicrocodeData, MicrocodeBufferSize);
+
+ return (EFI_PHYSICAL_ADDRESS) (UINTN) MicrocodeBuffer;
+ } else {
+ DEBUG(( DEBUG_ERROR, "Failed to allocate enough memory for Microcode Patch.\n"));
+ }
+ } else {
+ DEBUG(( DEBUG_ERROR, "Microcode patch size is greater than max allowed size of 128K.\n"));
+ }
+ return (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
+}
+#endif
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_CONFIG *CpuConfig;
+ CpuConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuConfig->Header.GuidHob.Name = %g\n", &CpuConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ CPU configuration
+ ********************************/
+ CpuConfig->AesEnable = CPU_FEATURE_ENABLE;
+ CpuConfig->EnableRsr = CPU_FEATURE_ENABLE;
+ CpuConfig->SmmbaseSwSmiNumber = (UINTN) PcdGet8 (PcdSmmbaseSwSmi);
+#ifndef FSP_FLAG
+ CpuConfig->MicrocodePatchAddress = PlatformCpuLocateMicrocodePatch ();
+#endif
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuPowerMgmtBasicConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_POWER_MGMT_BASIC_CONFIG *CpuPowerMgmtBasicConfig;
+ CPU_SKU CpuSku;
+ MSR_REGISTER TempMsr;
+
+ CpuPowerMgmtBasicConfig = ConfigBlockPointer;
+ CpuSku = GetCpuSku();
+
+ DEBUG ((DEBUG_INFO, "CpuPowerMgmtBasicConfig->Header.GuidHob.Name = %g\n", &CpuPowerMgmtBasicConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuPowerMgmtBasicConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuPowerMgmtBasicConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ CPU Power Management Basic configuration
+ ********************************/
+ CpuPowerMgmtBasicConfig->Hwp = TRUE;
+ CpuPowerMgmtBasicConfig->HdcControl = TRUE;
+ CpuPowerMgmtBasicConfig->PowerLimit2 = TRUE;
+ CpuPowerMgmtBasicConfig->PowerLimit3Lock = TRUE;
+ ///
+ /// Initialize RATL (Runtime Average Temperature Limit) Config for SKL Y series.
+ ///
+ if (CpuSku == EnumCpuUlx) {
+ CpuPowerMgmtBasicConfig->TccActivationOffset = 10;
+ CpuPowerMgmtBasicConfig->TccOffsetTimeWindowForRatl = 5000; // 5 sec
+ CpuPowerMgmtBasicConfig->TccOffsetClamp = CPU_FEATURE_ENABLE;
+ }
+ CpuPowerMgmtBasicConfig->TurboMode = TRUE;
+
+ TempMsr.Qword = AsmReadMsr64 (MSR_TURBO_RATIO_LIMIT);
+ CpuPowerMgmtBasicConfig->OneCoreRatioLimit = TempMsr.Bytes.FirstByte;
+ CpuPowerMgmtBasicConfig->TwoCoreRatioLimit = TempMsr.Bytes.SecondByte;
+ CpuPowerMgmtBasicConfig->ThreeCoreRatioLimit = TempMsr.Bytes.ThirdByte;
+ CpuPowerMgmtBasicConfig->FourCoreRatioLimit = TempMsr.Bytes.FouthByte;
+ CpuPowerMgmtBasicConfig->FiveCoreRatioLimit = TempMsr.Bytes.FifthByte;
+ CpuPowerMgmtBasicConfig->SixCoreRatioLimit = TempMsr.Bytes.SixthByte;
+ CpuPowerMgmtBasicConfig->SevenCoreRatioLimit = TempMsr.Bytes.SeventhByte;
+ CpuPowerMgmtBasicConfig->EightCoreRatioLimit = TempMsr.Bytes.EighthByte;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuPowerMgmtCustomConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_POWER_MGMT_CUSTOM_CONFIG *CpuPowerMgmtCustomConfig;
+ CpuPowerMgmtCustomConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuPowerMgmtCustomConfig->Header.GuidHob.Name = %g\n", &CpuPowerMgmtCustomConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuPowerMgmtCustomConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuPowerMgmtCustomConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ CPU Power Management Custom configuration
+ ********************************/
+ CpuPowerMgmtCustomConfig->CustomRatioTable.Cpuid = (UINT16) ((GetCpuFamily() | GetCpuStepping()) & (0x0FFF));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuTestConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_TEST_CONFIG *CpuTestConfig;
+ CPU_SKU CpuSku;
+ CpuTestConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuTestConfig->Header.GuidHob.Name = %g\n", &CpuTestConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuTestConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuTestConfig->Header.GuidHob.Header.HobLength));
+
+ CpuSku = GetCpuSku();
+ /********************************
+ CPU Test configuration
+ ********************************/
+ CpuTestConfig->MlcStreamerPrefetcher = CPU_FEATURE_ENABLE;
+ CpuTestConfig->MlcSpatialPrefetcher = CPU_FEATURE_ENABLE;
+ CpuTestConfig->MonitorMwaitEnable = CPU_FEATURE_ENABLE;
+ CpuTestConfig->MachineCheckEnable = CPU_FEATURE_ENABLE;
+ CpuTestConfig->DebugInterfaceLockEnable = CPU_FEATURE_ENABLE;
+ CpuTestConfig->ApIdleManner = 2; // AP Idle Manner default as Mwait Loop
+ CpuTestConfig->ApHandoffManner = 2; // AP Handoff to OS default as Mwait Loop
+ ///
+ /// Processor Trace
+ ///
+ CpuTestConfig->ProcTraceMemSize = EnumProcTraceMemDisable;
+
+ /**
+ This policy should be used to enable or disable Voltage Optimization feature.
+ Recommended defaults:
+ Enable - For Mobile SKUs(U/Y)
+ Disable - Rest of all SKUs other than Mobile.
+ **/
+ if ((CpuSku == EnumCpuUlx) || (CpuSku == EnumCpuUlt)){
+ CpuTestConfig->VoltageOptimization = CPU_FEATURE_ENABLE;
+ } else {
+ CpuTestConfig->VoltageOptimization = CPU_FEATURE_DISABLE;
+ }
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuPidTestConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_PID_TEST_CONFIG *CpuPidTestConfig;
+ CpuPidTestConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuPidTestConfig->Header.GuidHob.Name = %g\n", &CpuPidTestConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuPidTestConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuPidTestConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ CPU PID Test configuration
+ ********************************/
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuPowerMgmtTestConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_POWER_MGMT_TEST_CONFIG *CpuPowerMgmtTestConfig;
+ CPU_FAMILY CpuFamily;
+ CpuPowerMgmtTestConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuPowerMgmtTestConfig->Header.GuidHob.Name = %g\n", &CpuPowerMgmtTestConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuPowerMgmtTestConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuPowerMgmtTestConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ CPU Power Management Test configuration
+ ********************************/
+ CpuPowerMgmtTestConfig->Eist = TRUE;
+ CpuPowerMgmtTestConfig->EnergyEfficientPState = TRUE;
+ CpuPowerMgmtTestConfig->EnergyEfficientTurbo = TRUE;
+ CpuPowerMgmtTestConfig->BiProcHot = TRUE;
+ CpuPowerMgmtTestConfig->DisableProcHotOut = TRUE;
+ CpuPowerMgmtTestConfig->AutoThermalReporting = TRUE;
+ CpuPowerMgmtTestConfig->ThermalMonitor = TRUE;
+ CpuPowerMgmtTestConfig->Cx = TRUE;
+ CpuPowerMgmtTestConfig->PmgCstCfgCtrlLock = TRUE;
+ CpuPowerMgmtTestConfig->C1e = TRUE;
+ CpuPowerMgmtTestConfig->C1AutoDemotion = TRUE;
+ CpuPowerMgmtTestConfig->C1UnDemotion = TRUE;
+ CpuPowerMgmtTestConfig->C3AutoDemotion = TRUE;
+ CpuPowerMgmtTestConfig->C3UnDemotion = TRUE;
+ CpuPowerMgmtTestConfig->PkgCStateDemotion = TRUE;
+ CpuPowerMgmtTestConfig->PkgCStateUnDemotion = TRUE;
+ CpuPowerMgmtTestConfig->CStatePreWake = TRUE;
+ CpuPowerMgmtTestConfig->RaceToHalt = TRUE;
+ CpuPowerMgmtTestConfig->CstateLatencyControl0Irtl = C3_LATENCY;
+ CpuPowerMgmtTestConfig->CstateLatencyControl1Irtl = C6_C7_SHORT_LATENCY;
+ CpuPowerMgmtTestConfig->CstateLatencyControl2Irtl = C6_C7_LONG_LATENCY;
+ CpuPowerMgmtTestConfig->CstateLatencyControl3Irtl = C8_LATENCY;
+ CpuPowerMgmtTestConfig->CstateLatencyControl4Irtl = C9_LATENCY;
+ //
+ // If PS4 is disabled, program 2750us to MSR_C_STATE_LATENCY_CONTROL_5
+ //
+ CpuPowerMgmtTestConfig->CstateLatencyControl5Irtl = C10_LATENCY;
+ CpuPowerMgmtTestConfig->PkgCStateLimit = PkgAuto;
+ CpuPowerMgmtTestConfig->CstateLatencyControl0TimeUnit = TimeUnit1024ns;
+ CpuPowerMgmtTestConfig->CstateLatencyControl1TimeUnit = TimeUnit1024ns;
+ CpuPowerMgmtTestConfig->CstateLatencyControl2TimeUnit = TimeUnit1024ns;
+ CpuPowerMgmtTestConfig->CstateLatencyControl3TimeUnit = TimeUnit1024ns;
+ CpuPowerMgmtTestConfig->CstateLatencyControl4TimeUnit = TimeUnit1024ns;
+ CpuPowerMgmtTestConfig->CstateLatencyControl5TimeUnit = TimeUnit1024ns;
+ CpuPowerMgmtTestConfig->CustomPowerUnit = PowerUnit125MilliWatts;
+ CpuPowerMgmtTestConfig->PpmIrmSetting = PpmIrmPairFixedPriority;
+
+ //
+ // Pkg C-state Demotion/Un Demotion
+ //
+ CpuFamily = GetCpuFamily();
+ if((CpuFamily == EnumCpuSklUltUlx) || (CpuFamily == EnumCpuSklDtHalo)){
+ CpuPowerMgmtTestConfig->PkgCStateDemotion = TRUE;
+ } else if((CpuFamily == EnumCpuKblUltUlx) || (CpuFamily == EnumCpuKblDtHalo)) {
+ CpuPowerMgmtTestConfig->PkgCStateDemotion = FALSE;
+ }
+ if((CpuFamily == EnumCpuSklUltUlx) || (CpuFamily == EnumCpuSklDtHalo)){
+ CpuPowerMgmtTestConfig->PkgCStateDemotion = TRUE;
+ } else if((CpuFamily == EnumCpuKblUltUlx) || (CpuFamily == EnumCpuKblDtHalo)) {
+ CpuPowerMgmtTestConfig->PkgCStateDemotion = FALSE;
+ }
+}
+
+static COMPONENT_BLOCK_ENTRY mCpuIpBlocks [] = {
+ {&gCpuConfigGuid, sizeof (CPU_CONFIG), CPU_CONFIG_REVISION, LoadCpuConfigDefault},
+ {&gCpuPowerMgmtBasicConfigGuid, sizeof (CPU_POWER_MGMT_BASIC_CONFIG), CPU_POWER_MGMT_BASIC_CONFIG_REVISION, LoadCpuPowerMgmtBasicConfigDefault},
+ {&gCpuPowerMgmtCustomConfigGuid, sizeof (CPU_POWER_MGMT_CUSTOM_CONFIG), CPU_POWER_MGMT_CUSTOM_CONFIG_REVISION, LoadCpuPowerMgmtCustomConfigDefault},
+ {&gCpuTestConfigGuid, sizeof (CPU_TEST_CONFIG), CPU_TEST_CONFIG_REVISION, LoadCpuTestConfigDefault},
+ {&gCpuPidTestConfigGuid, sizeof (CPU_PID_TEST_CONFIG), CPU_PID_TEST_CONFIG_REVISION, LoadCpuPidTestConfigDefault},
+ {&gCpuPowerMgmtTestConfigGuid, sizeof (CPU_POWER_MGMT_TEST_CONFIG), CPU_POWER_MGMT_TEST_CONFIG_REVISION, LoadCpuPowerMgmtTestConfigDefault},
+};
+
+/**
+ Get CPU config block table total size.
+
+ @retval Size of CPU config block table
+**/
+UINT16
+EFIAPI
+CpuGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mCpuIpBlocks[0], sizeof (mCpuIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ CpuAddConfigBlocks add all Cpu config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add CPU config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CpuAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ EFI_STATUS Status;
+ DEBUG((DEBUG_INFO, "CPU Post-Mem Entry \n"));
+ PostCode (0xC00);
+
+ Status = AddComponentConfigBlocks (ConfigBlockTableAddress, &mCpuIpBlocks[0], sizeof (mCpuIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+ DEBUG ((DEBUG_INFO, "CpuAddConfigBlocks Done \n"));
+ PostCode (0xC09);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.inf
new file mode 100644
index 0000000000..24e9819e34
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.inf
@@ -0,0 +1,67 @@
+## @file
+# Component description file for the PeiCpuPolicyLib library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiCpuPolicyLib
+FILE_GUID = 5baafc8f-25c6-4d19-b141-585757509372
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = CpuPolicyLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+PeiServicesLib
+BaseMemoryLib
+MemoryAllocationLib
+CpuPlatformLib
+MmPciLib
+SaPlatformLib
+SiConfigBlockLib
+PostCodeLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PeiCpuPolicyLib.c
+PeiCpuPolicyLibrary.h
+CpuPrintPolicy.c
+
+[Ppis]
+gSiPolicyPpiGuid ## CONSUMES
+
+[FixedPcd]
+gSiPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase
+gSiPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSmmbaseSwSmi
+
+[Guids]
+gCpuConfigGuid ## PRODUCES
+gBiosGuardConfigGuid ## PRODUCES
+gCpuSgxConfigGuid ## PRODUCES
+gCpuPowerMgmtBasicConfigGuid ## PRODUCES
+gCpuPowerMgmtCustomConfigGuid ## PRODUCES
+gCpuTestConfigGuid ## PRODUCES
+gCpuPidTestConfigGuid ## PRODUCES
+gCpuPowerMgmtTestConfigGuid ## PRODUCES
+gCpuConfigLibPreMemConfigGuid ## PRODUCES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLibrary.h
new file mode 100644
index 0000000000..81301b475e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLibrary.h
@@ -0,0 +1,35 @@
+/** @file
+ Header file for the PeiCpuPolicyLib library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_CPU_POLICY_LIBRARY_H_
+#define _PEI_CPU_POLICY_LIBRARY_H_
+
+#include <PiPei.h>
+#include <CpuAccess.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/CpuPolicyLib.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Register/Cpuid.h>
+#include <Library/PcdLib.h>
+
+#define MAX_MICROCODE_PATCH_SIZE 0x20000
+
+#endif // _PEI_CPU_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/CpuPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/CpuPrintPolicy.c
new file mode 100644
index 0000000000..1807604405
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/CpuPrintPolicy.c
@@ -0,0 +1,102 @@
+/** @file
+ This file is PeiCpuPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiCpuPolicyLibrary.h"
+#include <Library/ConfigBlockLib.h>
+
+
+/**
+ Print CPU_CONFIG_LIB_PREMEM_CONFIG and serial out.
+
+ @param[in] CpuConfigLibPreMemConfig Pointer to a CPU_CONFIG_LIB_PREMEM_CONFIG
+
+**/
+VOID
+CpuConfigLibPreMemConfigPrint (
+ IN CONST CPU_CONFIG_LIB_PREMEM_CONFIG *CpuConfigLibPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ CPU Config Lib PreMem Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : HyperThreading = 0x%x\n", CpuConfigLibPreMemConfig->HyperThreading));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : CpuRatioOverride = 0x%x\n", CpuConfigLibPreMemConfig->CpuRatioOverride));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : BootFrequency = 0x%x\n", CpuConfigLibPreMemConfig->BootFrequency));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : ActiveCoreCount = 0x%x\n", CpuConfigLibPreMemConfig->ActiveCoreCount));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : FClkFrequency = 0x%x\n", CpuConfigLibPreMemConfig->FClkFrequency));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : JtagC10PowerGateDisable = 0x%x\n", CpuConfigLibPreMemConfig->JtagC10PowerGateDisable));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : BistOnReset = 0x%x\n", CpuConfigLibPreMemConfig->BistOnReset));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : VmxEnable = 0x%x\n", CpuConfigLibPreMemConfig->VmxEnable));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : CpuRatio = 0x%x\n", CpuConfigLibPreMemConfig->CpuRatio));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : PeciSxReset = 0x%x\n", CpuConfigLibPreMemConfig->PeciSxReset));
+ DEBUG ((DEBUG_INFO, "CPU_CONFIG_LIB_PREMEM_CONFIG : PeciC10Reset = 0x%x\n", CpuConfigLibPreMemConfig->PeciC10Reset));
+}
+
+/**
+ Print CPU_OVERCLOCKING_PREMEM_CONFIG and serial out.
+
+ @param[in] CpuOverClockingConfig Pointer to a CPU_OVERCLOCKING_CONFIG
+**/
+VOID
+CpuOverClockingPreMemConfigPrint (
+ IN CONST CPU_OVERCLOCKING_PREMEM_CONFIG *CpuOverClockingPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ CPU OverClocking Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: OcSupport : 0x%X\n", CpuOverClockingPreMemConfig->OcSupport));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: OcLock : 0x%X\n", CpuOverClockingPreMemConfig->OcLock));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: CoreVoltageMode : 0x%X\n", CpuOverClockingPreMemConfig->CoreVoltageMode));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: CorePllVoltageOffset : 0x%X\n", CpuOverClockingPreMemConfig->CorePllVoltageOffset));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: CoreMaxOcRatio : 0x%X\n", CpuOverClockingPreMemConfig->CoreMaxOcRatio));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: CoreVoltageOverride : 0x%X\n", CpuOverClockingPreMemConfig->CoreVoltageOverride));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: CoreVoltageAdaptive : 0x%X\n", CpuOverClockingPreMemConfig->CoreVoltageAdaptive));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: CoreVoltageOffset : 0x%X\n", CpuOverClockingPreMemConfig->CoreVoltageOffset));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: RingMaxOcRatio : 0x%X\n", CpuOverClockingPreMemConfig->RingMaxOcRatio));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: RingMinOcRatio : 0x%X\n", CpuOverClockingPreMemConfig->RingMinOcRatio));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: Avx2RatioOffset : 0x%X\n", CpuOverClockingPreMemConfig->Avx2RatioOffset));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: BclkAdaptiveVoltage : 0x%X\n", CpuOverClockingPreMemConfig->BclkAdaptiveVoltage));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: CorePllVoltageOffset : 0x%X\n", CpuOverClockingPreMemConfig->CorePllVoltageOffset));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: GtPllVoltageOffset : 0x%X\n", CpuOverClockingPreMemConfig->GtPllVoltageOffset));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: RingPllVoltageOffset : 0x%X\n", CpuOverClockingPreMemConfig->RingPllVoltageOffset));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: SaPllVoltageOffset : 0x%X\n", CpuOverClockingPreMemConfig->SaPllVoltageOffset));
+ DEBUG ((DEBUG_INFO, " CPU_OVERCLOCKING_PREMEM_CONFIG:: McPllVoltageOffset : 0x%X\n", CpuOverClockingPreMemConfig->McPllVoltageOffset));
+}
+
+
+/**
+ Print whole CPU Config blocks of SI_PREMEM_POLICY_PPI and serial out in PreMem.
+
+ @param[in] SiPreMemPolicyPpi The SI Pre-Mem Policy PPI instance
+**/
+VOID
+CpuPreMemPrintPolicy (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+ )
+{
+DEBUG_CODE_BEGIN();
+ EFI_STATUS Status;
+ CPU_CONFIG_LIB_PREMEM_CONFIG *CpuConfigLibPreMemConfig;
+ CPU_OVERCLOCKING_PREMEM_CONFIG *CpuOverclockingPreMemConfig;
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ CPU - SiPreMemPolicyPpi Print Begin in PreMem -----------------\n"));
+
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPreMemPolicyPpi->TableHeader.Header.Revision));
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuConfigLibPreMemConfigGuid, (VOID *) &CpuConfigLibPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuOverclockingPreMemConfigGuid, (VOID *) &CpuOverclockingPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ CpuConfigLibPreMemConfigPrint(CpuConfigLibPreMemConfig);
+ CpuOverClockingPreMemConfigPrint(CpuOverclockingPreMemConfig);
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ CPU - SiPreMemPolicyPpi Print End -----------------\n\n"));
+DEBUG_CODE_END();
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLib.c
new file mode 100644
index 0000000000..7d27c0b6dc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLib.c
@@ -0,0 +1,143 @@
+/** @file
+ This file is PeiCpuPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiCpuPolicyLibrary.h"
+#include <Library/MmPciLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PostCodeLib.h>
+#include <Library/SaPlatformLib.h>
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuConfigLibPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_CONFIG_LIB_PREMEM_CONFIG *CpuConfigLibPreMemConfig;
+ CPU_FAMILY CpuFamily;
+ CPU_SKU CpuSku;
+ BOOLEAN PegDisabled;
+ UINT64 MchBar;
+
+ CpuConfigLibPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuConfigLibPreMemConfig->Header.GuidHob.Name = %g\n", &CpuConfigLibPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuConfigLibPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuConfigLibPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ CPU Config Lib PreMem configuration
+ ********************************/
+ CpuConfigLibPreMemConfig->HyperThreading = CPU_FEATURE_ENABLE;
+ CpuConfigLibPreMemConfig->BootFrequency = 1; // Maximum non-turbo Performance
+ CpuConfigLibPreMemConfig->ActiveCoreCount = 0; // All cores active
+ CpuConfigLibPreMemConfig->VmxEnable = CPU_FEATURE_ENABLE;
+ CpuConfigLibPreMemConfig->CpuRatio = ((AsmReadMsr64 (MSR_PLATFORM_INFO) >> N_PLATFORM_INFO_MAX_RATIO) & B_PLATFORM_INFO_RATIO_MASK);
+ ///
+ /// FCLK Frequency
+ ///
+ CpuFamily = GetCpuFamily();
+ CpuSku = GetCpuSku();
+ MchBar = MmioRead64 (MmPciBase (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN) + R_SA_MCHBAR) &~BIT0;
+ if (IsPchLinkDmi (CpuFamily) && (MmioRead16 (MmPciBase (SA_PEG_BUS_NUM, SA_PEG_DEV_NUM, SA_PEG10_FUN_NUM) + PCI_VENDOR_ID_OFFSET) != 0xFFFF)) {
+ PegDisabled = MmioRead32 ((UINTN) MchBar + R_SA_MCHBAR_BIOS_RESET_CPL_OFFSET) & BIT3;
+ } else {
+ PegDisabled = 1;
+ }
+
+ ///
+ /// DT/Halo FCLK = 1GHz
+ /// Ulx/Ult FCLK = 800MHz
+ ///
+ if (((CpuSku == EnumCpuHalo) && (!PegDisabled)) || (CpuSku == EnumCpuTrad)) {
+ CpuConfigLibPreMemConfig->FClkFrequency = 1; // 1Ghz
+ } else {
+ CpuConfigLibPreMemConfig->FClkFrequency = 0; // 800MHz
+ }
+}
+
+/**
+ Load Overclocking pre-mem Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCpuOverclockingPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ CPU_OVERCLOCKING_PREMEM_CONFIG *CpuOverclockingPreMemConfig;
+ CpuOverclockingPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuOverclockingPreMemConfig->Header.GuidHob.Name = %g\n", &CpuOverclockingPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "CpuOverclockingPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", CpuOverclockingPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ CPU Overclocking PreMem configuration
+ ********************************/
+}
+
+
+static COMPONENT_BLOCK_ENTRY mCpuIpBlocksPreMem [] = {
+ {&gCpuConfigLibPreMemConfigGuid, sizeof (CPU_CONFIG_LIB_PREMEM_CONFIG), CPU_CONFIG_LIB_PREMEM_CONFIG_REVISION, LoadCpuConfigLibPreMemConfigDefault},
+ {&gCpuOverclockingPreMemConfigGuid, sizeof (CPU_OVERCLOCKING_PREMEM_CONFIG), CPU_OVERCLOCKING_PREMEM_CONFIG_REVISION,LoadCpuOverclockingPreMemConfigDefault},
+};
+
+/**
+ Get CPU PREMEM config block table total size.
+
+ @retval Size of CPU PREMEM config block table
+**/
+UINT16
+EFIAPI
+CpuGetPreMemConfigBlockTotalSize (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mCpuIpBlocksPreMem[0], sizeof (mCpuIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ CpuAddPreMemConfigBlocks add all CPU PREMEM config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add CPU PREMEM config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CpuAddPreMemConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ EFI_STATUS Status;
+ DEBUG((DEBUG_INFO, "CPU Pre-Mem Entry \n"));
+ PostCode (0xC00);
+
+ Status = AddComponentConfigBlocks (ConfigBlockTableAddress, &mCpuIpBlocksPreMem[0], sizeof (mCpuIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+ DEBUG((DEBUG_INFO, "CpuAddPreMemConfigBlocks Done \n"));
+ PostCode (0xC0F);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibPreMem.inf b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibPreMem.inf
new file mode 100644
index 0000000000..df6e20baef
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibPreMem.inf
@@ -0,0 +1,50 @@
+## @file
+# Component description file for the PeiCpuPolicyLibPreMem library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiCpuPolicyLibPreMem
+FILE_GUID = 5F4C2CF1-9DFE-4D99-9318-98FD31C8517D
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = CpuPolicyLibPreMem
+
+[LibraryClasses]
+DebugLib
+IoLib
+PeiServicesLib
+BaseMemoryLib
+MemoryAllocationLib
+CpuPlatformLib
+SiConfigBlockLib
+PostCodeLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PeiCpuPolicyLib.c
+PeiCpuPolicyLibrary.h
+CpuPrintPolicy.c
+
+[Ppis]
+gSiPreMemPolicyPpiGuid ## CONSUMES
+
+[Guids]
+gCpuSecurityPreMemConfigGuid ## PRODUCES
+gCpuTxtPreMemConfigGuid ## PRODUCES
+gCpuOverclockingPreMemConfigGuid ## PRODUCES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibrary.h
new file mode 100644
index 0000000000..8c039b4591
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibrary.h
@@ -0,0 +1,40 @@
+/** @file
+ Header file for the PeiCpuPolicyLib library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_CPU_POLICY_LIBRARY_H_
+#define _PEI_CPU_POLICY_LIBRARY_H_
+
+#include <PiPei.h>
+#include <Register/Cpuid.h>
+#include <CpuAccess.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/CpuPolicyLibPreMem.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/CpuPlatformLib.h>
+
+//
+// TXT configuration defines
+//
+#define TXT_SINIT_MEMORY_SIZE 0x50000
+#define TXT_HEAP_MEMORY_SIZE 0xE0000
+#define TXT_LCP_PD_BASE 0x0 ///< Platform default LCP
+#define TXT_LCP_PD_SIZE 0x0 ///< Platform default LCP
+#define TXT_TGA_MEMORY_SIZE 0x0 ///< Maximum 512K of TGA memory (aperture)
+
+#endif // _PEI_CPU_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c
new file mode 100644
index 0000000000..830803a909
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c
@@ -0,0 +1,466 @@
+/** @file
+ CPU Platform Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CpuPlatformLibrary.h"
+#include <Library/MmPciLib.h>
+#include <SaRegs.h>
+
+#define SKIP_MICROCODE_CHECKSUM_CHECK 1
+
+/**
+ Return CPU Family ID
+
+ @retval CPU_FAMILY CPU Family ID
+**/
+CPU_FAMILY
+EFIAPI
+GetCpuFamily (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ return ((CPU_FAMILY) (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL));
+}
+
+/**
+ Return Cpu stepping type
+
+ @retval UINT8 Cpu stepping type
+**/
+CPU_STEPPING
+EFIAPI
+GetCpuStepping (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ return ((CPU_STEPPING) (Cpuid.RegEax & CPUID_FULL_STEPPING));
+}
+
+/**
+ Return CPU Sku
+
+ @retval UINT8 CPU Sku
+**/
+UINT8
+EFIAPI
+GetCpuSku (
+ VOID
+ )
+{
+ UINT8 CpuType;
+ UINT16 CpuDid;
+ UINT32 CpuFamilyModel;
+ EFI_CPUID_REGISTER Cpuid;
+ BOOLEAN SkuFound;
+
+ SkuFound = TRUE;
+ CpuType = EnumCpuUnknown;
+
+ ///
+ /// Read the CPUID & DID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ CpuFamilyModel = Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL;
+ CpuDid = MmioRead16 (MmPciBase (0, 0, 0) + 2);
+
+ switch (CpuFamilyModel) {
+ case CPUID_FULL_FAMILY_MODEL_SKYLAKE_ULT_ULX:
+ switch (CpuDid) {
+ case V_SA_DEVICE_ID_SKL_MB_ULT_1: // ULT OPI
+ case V_SA_DEVICE_ID_KBL_MB_ULT_1: // KBL ULT OPI
+ CpuType = EnumCpuUlt;
+ break;
+
+ case V_SA_DEVICE_ID_SKL_MB_ULX_2: // ULX OPI
+ case V_SA_DEVICE_ID_SKL_MB_ULX_3: // ULX OPI
+ case V_SA_DEVICE_ID_KBL_MB_ULX_1: // ULX OPI
+ CpuType = EnumCpuUlx;
+ break;
+
+ default:
+ SkuFound = FALSE;
+ break;
+ }
+ break;
+
+ case CPUID_FULL_FAMILY_MODEL_SKYLAKE_DT_HALO:
+ switch (CpuDid) {
+
+ case V_SA_DEVICE_ID_SKL_DT_1: // DT
+ case V_SA_DEVICE_ID_SKL_DT_2: // DT
+ case V_SA_DEVICE_ID_KBL_DT_1: // DT
+ case V_SA_DEVICE_ID_KBL_DT_2: // DT
+ CpuType = EnumCpuTrad;
+ break;
+
+ case V_SA_DEVICE_ID_SKL_HALO_1: // Halo
+ case V_SA_DEVICE_ID_SKL_HALO_2: // Halo
+ case V_SA_DEVICE_ID_KBL_HALO_1: // Halo
+ case V_SA_DEVICE_ID_KBL_HALO_2: // Halo
+ case V_SA_DEVICE_ID_SKL_SVR_1: // Server
+ case V_SA_DEVICE_ID_SKL_SVR_2: // Server
+ case V_SA_DEVICE_ID_KBL_SVR_1: // Server
+ case V_SA_DEVICE_ID_KBL_SVR_2: // Server
+ CpuType = EnumCpuHalo;
+ break;
+
+ default:
+ SkuFound = FALSE;
+ break;
+ }
+ break;
+ case CPUID_FULL_FAMILY_MODEL_KABYLAKE_ULT_ULX:
+ switch (CpuDid) {
+ case V_SA_DEVICE_ID_KBL_MB_ULT_1: // KBL ULT OPI
+ case V_SA_DEVICE_ID_KBLR_MB_ULT_1: // KBL-R ULT
+ CpuType = EnumCpuUlt;
+ break;
+
+ case V_SA_DEVICE_ID_KBL_MB_ULX_1: // ULX OPI
+ CpuType = EnumCpuUlx;
+ break;
+
+ default:
+ SkuFound = FALSE;
+ break;
+ }
+ break;
+
+ case CPUID_FULL_FAMILY_MODEL_KABYLAKE_DT_HALO:
+ switch (CpuDid) {
+
+ case V_SA_DEVICE_ID_KBL_DT_1: // DT
+ case V_SA_DEVICE_ID_KBL_DT_2: // DT
+ case V_SA_DEVICE_ID_CFL_DT: // DT
+ CpuType = EnumCpuTrad;
+ break;
+
+ case V_SA_DEVICE_ID_KBL_HALO_1: // Halo
+ case V_SA_DEVICE_ID_KBL_HALO_2: // Halo
+ case V_SA_DEVICE_ID_KBL_SVR_1: // Server
+ case V_SA_DEVICE_ID_KBL_SVR_2: // Server
+ CpuType = EnumCpuHalo;
+ break;
+
+ default:
+ SkuFound = FALSE;
+ break;
+ }
+ break;
+
+ default:
+ SkuFound = FALSE;
+ break;
+ }
+
+ if (!SkuFound) {
+ DEBUG ((DEBUG_ERROR, "Unsupported CPU SKU, Device ID: 0x%02X, CPUID: 0x%08X!\n", CpuDid, CpuFamilyModel));
+ ASSERT (FALSE);
+ }
+
+ return CpuType;
+}
+
+
+/**
+ Returns the processor microcode revision of the processor installed in the system.
+
+ @retval Processor Microcode Revision
+**/
+UINT32
+GetCpuUcodeRevision (
+ VOID
+ )
+{
+ AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
+ return (UINT32) RShiftU64 (AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID), 32);
+}
+
+/**
+ Verify the DWORD type checksum
+
+ @param[in] ChecksumAddr - The start address to be checkumed
+ @param[in] ChecksumLen - The length of data to be checksumed
+
+ @retval EFI_SUCCESS - Checksum correct
+ @retval EFI_CRC_ERROR - Checksum incorrect
+**/
+EFI_STATUS
+Checksum32Verify (
+ IN UINT32 *ChecksumAddr,
+ IN UINT32 ChecksumLen
+ )
+{
+#if SKIP_MICROCODE_CHECKSUM_CHECK
+ return EFI_SUCCESS;
+#else
+ UINT32 Checksum;
+ UINT32 Index;
+
+ Checksum = 0;
+
+ for (Index = 0; Index < ChecksumLen; Index++) {
+ Checksum += ChecksumAddr[Index];
+ }
+
+ return (Checksum == 0) ? EFI_SUCCESS : EFI_CRC_ERROR;
+#endif
+}
+
+/**
+ This function checks the MCU revision to decide if BIOS needs to load
+ microcode.
+
+ @param[in] MicrocodePointer - Microcode in memory
+ @param[in] Revision - Current CPU microcode revision
+
+ @retval EFI_SUCCESS - BIOS needs to load microcode
+ @retval EFI_ABORTED - Don't need to update microcode
+**/
+EFI_STATUS
+CheckMcuRevision (
+ IN CPU_MICROCODE_HEADER *MicrocodePointer,
+ IN UINT32 Revision
+ )
+{
+ EFI_STATUS Status;
+ Status = EFI_ABORTED;
+
+ if ((MicrocodePointer->UpdateRevision & 0x80000000) ||
+ (MicrocodePointer->UpdateRevision > Revision) ||
+ (Revision == 0)) {
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Check if this microcode is correct one for processor
+
+ @param[in] Cpuid - processor CPUID
+ @param[in] MicrocodeEntryPoint - entry point of microcode
+ @param[in] Revision - revision of microcode
+
+ @retval CorrectMicrocode if this microcode is correct
+**/
+BOOLEAN
+CheckMicrocode (
+ IN UINT32 Cpuid,
+ IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint,
+ IN UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ UINT8 ExtendedIndex;
+ MSR_IA32_PLATFORM_ID_REGISTER Msr;
+ UINT32 ExtendedTableLength;
+ UINT32 ExtendedTableCount;
+ BOOLEAN CorrectMicrocode;
+ CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
+ CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
+
+ Status = EFI_NOT_FOUND;
+ ExtendedTableLength = 0;
+ CorrectMicrocode = FALSE;
+
+ if (MicrocodeEntryPoint == NULL) {
+ return FALSE;
+ }
+
+ Msr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
+
+ ///
+ /// Check if the microcode is for the Cpu and the version is newer
+ /// and the update can be processed on the platform
+ ///
+ if ((MicrocodeEntryPoint->HeaderVersion == 0x00000001) &&
+ !EFI_ERROR (CheckMcuRevision (MicrocodeEntryPoint, *Revision))
+ ) {
+ if ((MicrocodeEntryPoint->ProcessorId == Cpuid) && (MicrocodeEntryPoint->ProcessorFlags & (1 << (UINT8) Msr.Bits.PlatformId))) {
+ if (MicrocodeEntryPoint->DataSize == 0) {
+ Status = Checksum32Verify ((UINT32 *) MicrocodeEntryPoint, 2048 / sizeof (UINT32));
+ } else {
+ Status = Checksum32Verify (
+ (UINT32 *) MicrocodeEntryPoint,
+ (MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER)) / sizeof (UINT32)
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ CorrectMicrocode = TRUE;
+ }
+ } else if ((MicrocodeEntryPoint->DataSize != 0)) {
+ ///
+ /// Check the Extended Signature if the entended signature exist
+ /// Only the data size != 0 the extended signature may exist
+ ///
+ ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER));
+ if (ExtendedTableLength != 0) {
+ ///
+ /// Extended Table exist, check if the CPU in support list
+ ///
+ ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint) + MicrocodeEntryPoint->DataSize + 48);
+ ///
+ /// Calulate Extended Checksum
+ ///
+ if ((ExtendedTableLength % 4) == 0) {
+ Status = Checksum32Verify ((UINT32 *) ExtendedTableHeader, ExtendedTableLength / sizeof (UINT32));
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Checksum correct
+ ///
+ ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
+ ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
+ for (ExtendedIndex = 0; ExtendedIndex < ExtendedTableCount; ExtendedIndex++) {
+ ///
+ /// Verify Header
+ ///
+ if ((ExtendedTable->ProcessorSignature == Cpuid) && (ExtendedTable->ProcessorFlag & (1 << (UINT8) Msr.Bits.PlatformId))) {
+ Status = Checksum32Verify (
+ (UINT32 *) ExtendedTable,
+ sizeof (CPU_MICROCODE_EXTENDED_TABLE) / sizeof (UINT32)
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Find one
+ ///
+ CorrectMicrocode = TRUE;
+ break;
+ }
+ }
+
+ ExtendedTable++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return CorrectMicrocode;
+}
+
+
+/**
+ Check on the processor if SGX is supported.
+
+ @dot
+ digraph G {
+ subgraph cluster_c0 {
+ node [shape = box];
+ b1[label="Read CPUID(EAX=7,ECX=0):EBX[2] \nto check SGX feature" fontsize=12 style=filled color=lightblue];
+ b2[label="Return TRUE" fontsize=12 style=filled color=lightblue];
+ b3[label="Return FALSE" fontsize=12 style=filled color=lightblue];
+
+ node [shape = ellipse];
+ e1[label="Start" fontsize=12 style=filled color=lightblue];
+ e2[label="End" fontsize=12 style=filled color=lightblue];
+
+ node [shape = diamond,style=filled,color=lightblue];
+ d1[label="Are SGX feature supported and \nPRMRR configuration enabled" fontsize=12];
+
+ label = "IsSgxSupported Flow"; fontsize=15; fontcolor=black; color=lightblue;
+ e1 -> b1
+ b1 -> d1
+ d1 -> b2 [label="Yes" fontsize=9]
+ d1 -> b3 [label="No" fontsize=9]
+ b2 -> e2
+ b3 -> e2
+
+ }
+ }
+ @enddot
+
+ @retval TRUE if SGX supported
+ @retval FALSE if SGX is not supported
+**/
+BOOLEAN
+IsSgxSupported (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+
+ //
+ // Processor support SGX feature by reading CPUID.(EAX=7,ECX=0):EBX[2]
+ //
+ AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, &CpuidRegs.RegEax,&CpuidRegs.RegEbx,&CpuidRegs.RegEcx,&CpuidRegs.RegEdx);
+
+ ///
+ /// SGX feature is supported only on SKL and later,
+ /// with CPUID.(EAX=7,ECX=0):EBX[2]=1
+ /// PRMRR configuration enabled, MSR IA32_MTRRCAP (FEh) [12] == 1
+ ///
+ if (((CpuidRegs.RegEbx & BIT2)) && (AsmReadMsr64 (MSR_IA32_MTRRCAP) & BIT12)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Get processor generation
+
+ @retval EnumSklCpu Executing thread is Skylake
+ @retval EnumKblCpu Executing thread is Kabylake
+**/
+CPU_GENERATION
+GetCpuGeneration (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ CPU_FAMILY CpuFamilyModel;
+ CPU_STEPPING CpuStepping;
+ CPU_GENERATION CpuGeneration;
+
+ CpuGeneration = EnumSklCpu;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ CpuFamilyModel = (CPU_FAMILY) (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL);
+ CpuStepping = (CPU_STEPPING) (Cpuid.RegEax & CPUID_FULL_STEPPING);
+
+ switch (CpuFamilyModel) {
+ case EnumCpuKblUltUlx:
+ case EnumCpuKblDtHalo:
+ CpuGeneration = EnumKblCpu;
+ break;
+
+ case EnumCpuSklUltUlx:
+ case EnumCpuSklDtHalo:
+ if (((CpuStepping > EnumSklMaxUltUlxStep) && (CpuStepping <= EnumKblMaxUltUlxStep)) ||
+ ((CpuStepping > EnumSklMaxDtHaloStep) && (CpuStepping <= EnumKblMaxDtHaloStep))) {
+ CpuGeneration = EnumKblCpu;
+ }
+ break;
+
+ default:
+ CpuGeneration = EnumSklCpu;
+ break;
+ }
+
+ return CpuGeneration;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h
new file mode 100644
index 0000000000..d5b8ed9ae4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h
@@ -0,0 +1,34 @@
+/** @file
+ Header file for Cpu Platform Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+#define _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SynchronizationLib.h>
+
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+#include <CpuAccess.h>
+#include <Library/CpuPlatformLib.h>
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf
new file mode 100644
index 0000000000..2a123ae708
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf
@@ -0,0 +1,50 @@
+## @file
+# Component description file for CPU Platform Lib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmCpuPlatformLib
+FILE_GUID = 11647130-6AA4-41A4-A3A8-5FA296ABD977
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = CpuPlatformLib
+
+
+[LibraryClasses]
+BaseLib
+BaseMemoryLib
+DebugLib
+IoLib
+PcdLib
+PciLib
+CpuLib
+TimerLib
+SynchronizationLib
+MmPciLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+
+[Sources]
+CpuPlatformLibrary.h
+CpuPlatformLibrary.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/CpuCommonLib.c b/Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/CpuCommonLib.c
new file mode 100644
index 0000000000..100bd1464c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/CpuCommonLib.c
@@ -0,0 +1,562 @@
+/** @file
+ CPU Common Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/TimerLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/CpuMailboxLib.h>
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+#include <CpuAccess.h>
+
+#include <Library/CpuCommonLib.h>
+
+#define INTERRUPT_VECTOR_NUMBER 256
+#define END_OF_TIMETABLE 0x3FF
+
+
+/**
+ Set up flags in CR4 for XMM instruction enabling
+**/
+VOID
+EFIAPI
+XmmInit (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ UINTN Cr0;
+ UINTN Cr4;
+
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+
+ ///
+ /// Check whether SSE2 is supported
+ ///
+ if (Cpuid.RegEdx & BIT26) {
+ ///
+ /// Enable XMM
+ ///
+ Cr0 = AsmReadCr0 ();
+ Cr0 |= BIT1;
+ AsmWriteCr0 (Cr0);
+
+ Cr4 = AsmReadCr4 ();
+ Cr4 |= (UINTN) (BIT9 | BIT10);
+ AsmWriteCr4 (Cr4);
+ }
+}
+
+/**
+ Enable "Machine Check Enable" bit in Cr4
+**/
+VOID
+EFIAPI
+EnableMce (
+ VOID
+ )
+{
+ UINTN Cr4;
+
+ ///
+ /// Enable MCE
+ ///
+ Cr4 = AsmReadCr4 ();
+ Cr4 |= BIT6;
+ AsmWriteCr4 (Cr4);
+}
+
+/**
+ Mtrr Synch Up Entry
+**/
+UINTN
+EFIAPI
+MpMtrrSynchUpEntry (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ UINT64 MsrData;
+ UINTN Cr0;
+ UINTN Cr4;
+
+ ///
+ /// Read the CPUID and MSR 1Bh information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ MsrData = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+
+ ///
+ /// Set CD(Bit30) bit and clear NW(Bit29) bit of CR0 followed by a WBINVD.
+ ///
+ if (!(Cpuid.RegEdx & BIT24) || (MsrData & BIT8)) {
+ AsmDisableCache ();
+ } else {
+ ///
+ /// We could bypass the wbinvd by
+ /// checking MSR 1Bh(MSR_IA32_APIC_BASE) Bit8 (1 = BSP, 0 = AP) to see if we're the BSP?
+ /// and checking CPUID if the processor support self-snooping.
+ ///
+ Cr0 = AsmReadCr0 ();
+ Cr0 &= (UINTN) ~BIT29;
+ Cr0 |= BIT30;
+ AsmWriteCr0 (Cr0);
+ }
+
+ ///
+ /// Clear PGE flag Bit 7
+ ///
+ Cr4 = AsmReadCr4 ();
+ Cr4 &= (UINTN) ~BIT7;
+ AsmWriteCr4 (Cr4);
+
+ ///
+ /// Flush all TLBs
+ ///
+ CpuFlushTlb ();
+
+ return Cr4;
+}
+
+/**
+ Mtrr Synch Up Exit
+**/
+VOID
+EFIAPI
+MpMtrrSynchUpExit (
+ UINTN Cr4
+ )
+{
+ UINTN Cr0;
+
+ ///
+ /// Flush all TLBs the second time
+ ///
+ CpuFlushTlb ();
+
+ ///
+ /// Clear both the CD and NW bits of CR0.
+ ///
+ Cr0 = AsmReadCr0 ();
+ Cr0 &= (UINTN) ~(BIT29 | BIT30);
+ AsmWriteCr0 (Cr0);
+
+ ///
+ /// Set PGE Flag in CR4 if set
+ ///
+ AsmWriteCr4 (Cr4);
+}
+
+/**
+ This procedure sends an IPI to the designated processor in
+ the requested delivery mode with the requested vector.
+
+ @param[in] ApicID - APIC ID of processor.
+ @param[in] VectorNumber - Vector number.
+ @param[in] DeliveryMode - I/O APIC Interrupt Deliver Modes
+
+ @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
+ @retval EFI_NOT_READY - There was a pending interrupt
+ @retval EFI_SUCCESS - Interrupt sent successfully
+**/
+EFI_STATUS
+EFIAPI
+CpuSendIpi (
+ IN UINT32 ApicID,
+ IN UINTN VectorNumber,
+ IN UINTN DeliveryMode
+ )
+{
+ MSR_IA32_APIC_BASE_REGISTER Msr;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT32 IcrLow;
+ UINT32 IcrHigh;
+ BOOLEAN XapicEnabled;
+ UINT32 TriggerMode;
+
+ ///
+ /// Check for valid input parameters.
+ ///
+ if (VectorNumber >= INTERRUPT_VECTOR_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DeliveryMode >= DELIVERY_MODE_MAX) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ///
+ /// Fix the vector number for special interrupts like SMI and INIT.
+ ///
+ if (DeliveryMode == DELIVERY_MODE_SMI || DeliveryMode == DELIVERY_MODE_INIT) {
+ VectorNumber = 0x0;
+ }
+
+ ///
+ /// Initialze ICR high dword, since P6 family processor needs
+ /// the destination field to be 0x0F when it is a broadcast
+ ///
+ IcrHigh = 0x0f000000;
+ IcrLow = (UINT32) (VectorNumber | (LShiftU64 (DeliveryMode, 8)));
+
+ TriggerMode = TRIGGER_MODE_EDGE;
+
+ ///
+ /// Interrupt trigger mode
+ ///
+ if (TriggerMode == TRIGGER_MODE_LEVEL) {
+ IcrLow |= 0x8000;
+ }
+
+ ///
+ /// Interrupt pin polarity
+ ///
+ IcrLow |= 0x4000;
+
+ ///
+ /// xAPIC Enabled
+ ///
+ Msr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ XapicEnabled = (BOOLEAN) ((Msr.Bits.EXTD == 1) && (Msr.Bits.EN == 1));
+
+ if (XapicEnabled) {
+ IcrHigh = (UINT32) ApicID;
+ } else {
+ IcrHigh = (UINT32) LShiftU64 (ApicID, 24);
+ }
+
+ ApicBase = Msr.Uint64 & 0xffffff000;
+
+ /* If Extended XAPIC Mode is enabled,
+ legacy xAPIC is no longer working.
+ So, previous MMIO offset must be transferred to MSR offset R/W.
+ ----------------------------------------------------------------
+ MMIO Offset MSR Offset Register Name
+ ----------------------------------------------------------------
+ 300h-310h 830h Interrupt Command Register [63:0]
+ 831h [Reserved]
+ ----------------------------------------------------------------
+ */
+ ///
+ /// To write APIC register by MSR or MMIO
+ ///
+ if (XapicEnabled) {
+ AsmWriteMsr64 (MSR_IA32_X2APIC_ICR, (((UINT64) LShiftU64 (IcrHigh, 32)) | (UINT64) IcrLow));
+ } else {
+ *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_HIGH_OFFSET) = (UINT32) IcrHigh;
+ *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET) = (UINT32) IcrLow;
+ }
+
+ MicroSecondDelay (10);
+
+ ///
+ /// To get APIC register from MSR or MMIO
+ ///
+ if (XapicEnabled) {
+ IcrLow = (UINT32) AsmReadMsr64 (MSR_IA32_X2APIC_ICR);
+ } else {
+ IcrLow = (UINT32) *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET);
+ }
+
+ if (IcrLow & BIT12) {
+ return EFI_NOT_READY;
+ }
+
+ MicroSecondDelay (100);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get APIC ID of processor
+
+ @retval APIC ID of processor
+**/
+UINT32
+GetCpuApicId (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ return (UINT32) (CpuidRegisters.RegEbx >> 24);
+}
+
+/**
+ Programs XAPIC registers.
+
+ @param[in] Bsp - Is this BSP?
+**/
+VOID
+ProgramXApic (
+ BOOLEAN Bsp
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ volatile UINT32 *EntryAddress;
+ UINT32 EntryValue;
+
+ ApicBaseReg = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & 0xffffff000ULL;
+
+ ///
+ /// Program the spurious vector entry
+ ///
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+ EntryValue &= 0xFFFFFD0F;
+ EntryValue |= 0x10F;
+ *EntryAddress = EntryValue;
+
+ ///
+ /// Program the LINT1 vector entry as extINT
+ ///
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+
+ if (Bsp) {
+ EntryValue &= 0xFFFE00FF;
+ EntryValue |= 0x700;
+ } else {
+ EntryValue |= 0x10000;
+ }
+
+ *EntryAddress = EntryValue;
+
+ ///
+ /// Program the LINT1 vector entry as NMI
+ ///
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_LINT1_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+ EntryValue &= 0xFFFE00FF;
+ if (Bsp) {
+ EntryValue |= 0x400;
+ } else {
+ EntryValue |= 0x10400;
+ }
+
+ *EntryAddress = EntryValue;
+}
+
+/**
+ This function is to disable BIOS Write Protect in SMM phase.
+**/
+VOID
+EFIAPI
+CpuSmmDisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ ///
+ /// Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ ///
+ Data32 = MmioRead32 ((UINTN) (0xFED30880)) | (UINT32) (BIT0);
+ AsmWriteMsr32 (0x000001FE, Data32);
+}
+
+/**
+ This function is to enable BIOS Write Protect in SMM phase.
+**/
+VOID
+EFIAPI
+CpuSmmEnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ ///
+ /// Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ ///
+ Data32 = MmioRead32 ((UINTN) (0xFED30880)) & (UINT32) (~BIT0);
+ AsmWriteMsr32 (0x000001FE, Data32);
+}
+
+/**
+ This function returns the maximum number of cores supported in this physical processor package.
+
+ @retval Maximum number of supported cores in the package.
+**/
+UINT8
+GetMaxSupportedCoreCount (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ AsmCpuidEx (
+ 4,
+ 0,
+ &Cpuid.RegEax,
+ NULL,
+ NULL,
+ NULL
+ );
+ return (UINT8) (RShiftU64 (Cpuid.RegEax, 26) & 0x3f) + 1;
+}
+
+/**
+ This function returns the actual factory-configured number of threads per core,
+ and actual factory-configured number of cores in this physical processor package.
+
+ @param[out] *ThreadsPerCore - variable that will store Maximum enabled threads per core
+ @param[out] *NumberOfCores - variable that will store Maximum enabled cores per die
+**/
+VOID
+GetSupportedCount (
+ OUT UINT16 *ThreadsPerCore, OPTIONAL
+ OUT UINT16 *NumberOfCores OPTIONAL
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+ UINT16 Threads;
+
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &CpuidRegs.RegEbx, NULL, NULL);
+ Threads = (UINT16) CpuidRegs.RegEbx;
+
+ if (ThreadsPerCore != NULL) {
+ *ThreadsPerCore = Threads;
+ }
+
+ if (NumberOfCores != NULL) {
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 1, NULL, &CpuidRegs.RegEbx, NULL, NULL);
+ *NumberOfCores = (UINT16) (CpuidRegs.RegEbx / Threads);
+ }
+}
+
+
+/**
+ Check to see if the executing thread is BSP
+
+ @retval TRUE Executing thread is BSP
+ @retval FALSE Executing thread is AP
+**/
+BOOLEAN
+IsBsp (
+ VOID
+ )
+{
+ MSR_IA32_APIC_BASE_REGISTER Msr;
+
+ Msr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ return (BOOLEAN) (Msr.Bits.BSP == 1);
+}
+
+
+BOOLEAN
+IsPrmrrAlreadySet (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+/**
+ Check if this is non-core processor - HT AP thread
+
+ @retval TRUE if this is HT AP thread
+ @retval FALSE if this is core thread
+**/
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ )
+{
+ UINT32 ApicID;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT8 CpuCount;
+ UINT8 CoreCount;
+ UINT8 CpuPerCore;
+ UINT32 Mask;
+
+ ApicID = GetCpuApicId ();
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEdx & 0x10000000) == 0) {
+ return FALSE;
+ }
+
+ CpuCount = (UINT8) ((CpuidRegisters.RegEbx >> 16) & 0xff);
+ if (CpuCount == 1) {
+ return FALSE;
+ }
+
+ AsmCpuid (
+ CPUID_SIGNATURE,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if (CpuidRegisters.RegEax > 3) {
+
+ CoreCount = GetMaxSupportedCoreCount ();
+ } else {
+ CoreCount = 1;
+ }
+ ///
+ /// Assumes there is symmetry across core boundary, i.e. each core within a package has the same number of logical processors
+ ///
+ if (CpuCount == CoreCount) {
+ return FALSE;
+ }
+
+ CpuPerCore = CpuCount / CoreCount;
+
+ ///
+ /// Assume 1 Core has no more than 8 threads
+ ///
+ if (CpuPerCore == 2) {
+ Mask = 0x1;
+ } else if (CpuPerCore <= 4) {
+ Mask = 0x3;
+ } else {
+ Mask = 0x7;
+ }
+
+ if ((ApicID & Mask) == 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/PeiDxeSmmCpuCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/PeiDxeSmmCpuCommonLib.inf
new file mode 100644
index 0000000000..70d33ce354
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/PeiDxeSmmCpuCommonLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for CPU Common Lib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmCpuCommonLib
+FILE_GUID = B4E0E3E8-DCE9-46FE-9670-03FDD2F08D6C
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = CpuCommonLib
+
+
+[LibraryClasses]
+BaseLib
+BaseMemoryLib
+DebugLib
+IoLib
+PcdLib
+PciLib
+CpuLib
+TimerLib
+SynchronizationLib
+TimerLib
+CpuPlatformLib
+CpuMailboxLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+CpuCommonLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/BootFirmwareMediaProtection.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/BootFirmwareMediaProtection.c
new file mode 100644
index 0000000000..bf272036c4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/BootFirmwareMediaProtection.c
@@ -0,0 +1,399 @@
+/** @file
+ This file contains the tests for the BootFirmwareMediaProtection BIT
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+#define B_PCH_SPI_FMRWA_MASK 0xFFF00000
+#define B_PCH_SPI_FMRRA_MASK 0x000FFF00
+
+/**
+ Run tests for BootFirmwareMediaProtection bit
+**/
+VOID
+CheckBootFirmwareMediaProtection (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINT16 PmBase;
+ UINT8 BiosControl;
+ UINT16 Hsfs;
+ UINT32 Cpptv;
+ UINT32 Frap;
+ UINT8 Data8;
+ UINT32 Data32;
+ CHAR16 *HstiErrorString;
+ UINT32 PchSpiBar0;
+ UINT8 PcrDmi;
+
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+
+ PchAcpiBaseGet (&PmBase);
+
+ PchSpiBar0 = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_SPI,PCI_FUNCTION_NUMBER_PCH_SPI) + R_PCH_SPI_BAR0) & ~B_PCH_SPI_BAR0_MASK;
+
+ DEBUG ((DEBUG_INFO, " Table 3-5. SPI Flash and BIOS Security Configuration\n"));
+ DEBUG ((DEBUG_INFO, " 1. BIOS write-protection\n"));
+
+ BiosControl = MmioRead8 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_LPC,PCI_FUNCTION_NUMBER_PCH_SPI) + R_PCH_SPI_BC);
+ if (((BiosControl & B_PCH_SPI_BC_LE) == 0) ||
+ ((BiosControl & B_PCH_SPI_BC_WPD) != 0) ||
+ ((BiosControl & B_PCH_SPI_BC_EISS) == 0)) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_1 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. SPI flash descriptor security override pin-strap\n"));
+
+ Hsfs = MmioRead16 (PchSpiBar0 + R_PCH_SPI_HSFSC);
+ if ((Hsfs & B_PCH_SPI_HSFSC_FDOPSS) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_2 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 3. SPI controller configuration is locked\n"));
+
+ if ((Hsfs & B_PCH_SPI_HSFSC_FLOCKDN) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_3 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_3);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 4. BIOS Interface Lock\n"));
+
+ PcrDmi = MmioRead8 (PCH_PCR_ADDRESS (PID_DMI,R_PCH_PCR_DMI_GCS));
+
+ if (((PcrDmi & BIT0) == 0x0) ||
+ ((BiosControl & BIT7) == 0x0)) {
+ DEBUG ((DEBUG_INFO, "PcrDmi %x or BILD[7] %x not set\n",PcrDmi,BiosControl));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_4 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_4);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 5. BIOS Top Swap Mode\n"));
+
+ if ((BiosControl & B_PCH_SPI_BC_TSS) != 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_5 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_5);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 6. Component Property Parameter Table Valid\n"));
+
+ Cpptv = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0);
+ if ((Cpptv & B_PCH_SPI_SFDPX_VSCCX_CPPTV) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_6 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_6);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 7. Component Property Parameter Table Valid, Secondary Flash Part\n"));
+ Data32 = 0;
+ Data32 = Data32 | 0x14;
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDOC, Data32);
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+
+ Cpptv = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP1_VSCC1);
+
+ //
+ // If Second part is present the verify CPPTV is set, otherwise if not present verify that it's clear
+ //
+ if ((Data32 & BIT8) != 0) {
+ if ((Cpptv & B_PCH_SPI_SFDPX_VSCCX_CPPTV) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_6 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_6);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ } else {
+ if ((Cpptv & B_PCH_SPI_SFDPX_VSCCX_CPPTV) == 1) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_6 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_6);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, " 8. ME Firmware Status\n"));
+
+ Data8 = MmioRead8 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,ME_DEVICE_NUMBER,HECI_FUNCTION_NUMBER) + 0x40);
+ if ((Data8 & 0xF) != 0x5) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_8 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_8);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 9. BIOS Flash Descriptor Valid\n"));
+
+ if ((Hsfs & B_PCH_SPI_HSFSC_FDV) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_9 ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_9);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ Data32 = 0;
+ Data32 = Data32 | V_PCH_SPI_FDOC_FDSS_MSTR | 0x0;
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDOC, Data32);
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+
+ DEBUG ((DEBUG_INFO, " 11. BIOS Region Flash Write Access\n"));
+ ///
+ /// Descriptor Master Access Read: BIT 8
+ /// Bios Master Access Read: BIT 9
+ /// CSE Master Access Read: BIT 10
+ /// GBE Master Access Read: BIT 11
+ /// PDR Master Access Read: BIT 12
+ /// EC Master Access Read: BIT 16
+ /// Descriptor Master Access Write: BIT 20
+ /// Bios Master Access Write: BIT 21
+ /// CSE Master Access Write: BIT 22
+ /// GBE Master Access Write: BIT 23
+ /// PDR Master Access Write: BIT 24
+ /// EC Master Access Write: BIT 28
+ ///
+ if (((Data32 & B_PCH_SPI_FMRWA_MASK) != 0x00A00000) &&
+ ((Data32 & B_PCH_SPI_FMRWA_MASK) != 0x01A00000) &&
+ ((Data32 & B_PCH_SPI_FMRWA_MASK) != 0x10A00000) &&
+ ((Data32 & B_PCH_SPI_FMRWA_MASK) != 0x11A00000)) {
+
+ DEBUG ((DEBUG_INFO, "Bios Region Master Write Access 0x%x\n",(Data32 & B_PCH_SPI_FMRWA_MASK)));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 12. BIOS Region Flash Read Access\n"));
+
+ if (((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00000F00) &&
+ ((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00001F00) &&
+ ((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00010F00) &&
+ ((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00011F00) &&
+ ((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00000B00) &&
+ ((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00001B00) &&
+ ((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00010B00) &&
+ ((Data32 & B_PCH_SPI_FMRRA_MASK) != 0x00011B00)) {
+
+ DEBUG ((DEBUG_INFO, "Bios Region Master Read Access 0x%x\n",(Data32 & B_PCH_SPI_FMRRA_MASK)));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 13. BIOS Master Read Access\n"));
+ Frap = MmioRead16 (PchSpiBar0+ R_PCH_SPI_FRAP);
+
+ if ((Frap & B_PCH_SPI_FRAP_BMRAG_MASK) != 0) {
+ DEBUG ((DEBUG_INFO, "BMRAG 0x%x\n",(Frap & B_PCH_SPI_FRAP_BMRAG_MASK)));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 14. BIOS Master Write Access\n"));
+
+ if ((Frap & B_PCH_SPI_FRAP_BMWAG_MASK) != 0) {
+ DEBUG ((DEBUG_INFO, "BMWAG 0x%x\n",(Frap & B_PCH_SPI_FRAP_BMWAG_MASK)));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ if (PchIsGbeRegionValid ()) {
+ DEBUG ((DEBUG_INFO, " 15. GbE Region Access\n"));
+
+ Data32 = 0;
+ Data32 = Data32 | V_PCH_SPI_FDOC_FDSS_MSTR | 0x8;
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDOC, Data32);
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+
+ if (Data32 != 0x00800900) {
+ DEBUG ((DEBUG_INFO, "Gbe Region Access 0x%x\n",Data32));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, " 16. CSME Region Access\n"));
+
+ Data32 = 0;
+ Data32 = Data32 | V_PCH_SPI_FDOC_FDSS_MSTR | 0x4;
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDOC, Data32);
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+
+ if ((Data32 != 0x00400D00) &&
+ (Data32 != 0x00C00D00) &&
+ (Data32 != 0x10C10D00)) {
+ DEBUG ((DEBUG_INFO, "Csme Region Access 0x%x\n",Data32));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 17. EC Region Access\n"));
+
+ Data32 = 0;
+ Data32 = Data32 | V_PCH_SPI_FDOC_FDSS_MSTR | 0x10;
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDOC, Data32);
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+
+ if ((Data32 != 0x10010300)&&
+ (Data32 != 0x10010100)&&
+ (Data32 != 0x10010000)) {
+ DEBUG ((DEBUG_INFO, "Ec Region access 0x%x\n",Data32));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A ,HSTI_SPI_FLASH_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 0,
+ HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/DebugModeDisabled.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/DebugModeDisabled.c
new file mode 100644
index 0000000000..e96535cf03
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/DebugModeDisabled.c
@@ -0,0 +1,94 @@
+/** @file
+ This file contains the tests for the DebugModeDisabled Bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for DebugModeDisabled bit
+**/
+VOID
+CheckDebugModeDisabled (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINT32 RegEcx;
+ UINT64 DebugInterface;
+ CHAR16 *HstiErrorString;
+
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+
+ DEBUG ((DEBUG_INFO, " Debug Interface check\n"));
+
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &RegEcx, NULL);
+
+ if ((RegEcx & BIT11) != 0) {
+
+ DebugInterface = AsmReadMsr64 (MSR_IA32_DEBUG_INTERFACE);
+
+ DEBUG ((DEBUG_INFO, " 1. Disabled Check\n"));
+
+ if ((DebugInterface & B_DEBUG_INTERFACE_ENABLE) != 0) {
+ DEBUG ((DEBUG_INFO, "Fail: Debug Interface Enabled\n"));
+
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_CODE_1 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. Locked\n"));
+
+ if ((DebugInterface & B_DEBUG_INTERFACE_LOCK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: Debug interface not locked\n"));
+
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_CODE_2 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 0,
+ HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HardwareRootedBootIntegrity.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HardwareRootedBootIntegrity.c
new file mode 100644
index 0000000000..beca056028
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HardwareRootedBootIntegrity.c
@@ -0,0 +1,30 @@
+/** @file
+ This file contains the tests for the HardwareRootedBootIntegrity bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for HardwareRootedBootIntegrity bit
+**/
+VOID
+CheckHardwareRootedBootIntegrity (
+ VOID
+ )
+{
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_HARDWARE_ROOTED_BOOT_INTEGRITY) == 0) {
+ return;
+ }
+
+ return ;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.c
new file mode 100644
index 0000000000..e9a26cac80
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.c
@@ -0,0 +1,387 @@
+/** @file
+ This file contains DXE driver for testing and publishing HSTI
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+ADAPTER_INFO_PLATFORM_SECURITY_STRUCT mHstiStruct = {
+ PLATFORM_SECURITY_VERSION_VNEXTCS,
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ {HSTI_PLATFORM_NAME},
+ HSTI_SECURITY_FEATURE_SIZE,
+ {0}, // SecurityFeaturesRequired
+ {0}, // SecurityFeaturesImplemented
+ {0}, // SecurityFeaturesVerified
+ 0,
+};
+
+UINT8 mFeatureRequired[HSTI_SECURITY_FEATURE_SIZE] = {
+ //
+ // Byte 0
+ //
+ FixedPcdGet8 (PcdHstiIhvFeature1),
+ //
+ // Byte 1
+ //
+ FixedPcdGet8 (PcdHstiIhvFeature2),
+ //
+ // Byte 2
+ //
+ FixedPcdGet8 (PcdHstiIhvFeature3),
+};
+
+UINT8 mFeatureImplemented[HSTI_SECURITY_FEATURE_SIZE] = {
+ //
+ // Byte 0
+ //
+ FixedPcdGet8 (PcdHstiIhvFeature1),
+ //
+ // Byte 1
+ //
+ FixedPcdGet8 (PcdHstiIhvFeature2),
+ //
+ // Byte 2
+ //
+ FixedPcdGet8 (PcdHstiIhvFeature3),
+};
+
+DXE_SI_POLICY_PROTOCOL *mSiPolicyData;
+
+/**
+ Initialize HSTI feature data
+**/
+VOID
+InitData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ADAPTER_INFO_PLATFORM_SECURITY *Hsti;
+ UINT8 *SecurityFeatures;
+ UINTN Index;
+
+ if ((mSiPolicyData != NULL) && (mSiPolicyData->Hsti != NULL)) {
+
+ ///
+ /// Take cached HSTI feature bitmap data pointed to by policy and publish to OS
+ ///
+ Hsti = mSiPolicyData->Hsti;
+
+ SecurityFeatures = (UINT8 *) (Hsti + 1);
+ DEBUG ((DEBUG_INFO, " SecurityFeaturesRequired - "));
+ for (Index = 0; Index < Hsti->SecurityFeaturesSize; Index++) {
+ DEBUG ((DEBUG_INFO, "%02x ", SecurityFeatures[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ CopyMem (mHstiStruct.SecurityFeaturesRequired, SecurityFeatures, sizeof (mFeatureRequired));
+
+ SecurityFeatures = (UINT8 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+ DEBUG ((DEBUG_INFO, " SecurityFeaturesImplemented - "));
+ for (Index = 0; Index < Hsti->SecurityFeaturesSize; Index++) {
+ DEBUG ((DEBUG_INFO, "%02x ", SecurityFeatures[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ CopyMem (mHstiStruct.SecurityFeaturesImplemented, SecurityFeatures, sizeof (mFeatureImplemented));
+
+ SecurityFeatures = (UINT8 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+ DEBUG ((DEBUG_INFO, " SecurityFeaturesVerified - "));
+ for (Index = 0; Index < Hsti->SecurityFeaturesSize; Index++) {
+ DEBUG ((DEBUG_INFO, "%02x ", SecurityFeatures[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ CopyMem (mHstiStruct.SecurityFeaturesVerified, SecurityFeatures, sizeof (mFeatureImplemented));
+ } else {
+ ///
+ /// Set only the bitmaps not related to verified, those will get updated during test process
+ ///
+ CopyMem (mHstiStruct.SecurityFeaturesRequired, mFeatureRequired, sizeof (mFeatureRequired));
+ CopyMem (mHstiStruct.SecurityFeaturesImplemented, mFeatureImplemented, sizeof (mFeatureImplemented));
+ }
+ Status = HstiLibSetTable (
+ &mHstiStruct,
+ sizeof (mHstiStruct)
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_ALREADY_STARTED) {
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+}
+
+/**
+ Concatenate error string.
+
+ @param[in] ErrorCodeString - Error Code
+ @param[in] ErrorCategoryString - Error Category
+ @param[in] ErrorString - Error Text
+
+ @retval CHAR16 - Concatenated string.
+**/
+CHAR16 *
+EFIAPI
+BuildHstiErrorString (
+ IN CHAR16 *ErrorCodeString,
+ IN CHAR16 *ErrorCategoryString,
+ IN CHAR16 *ErrorString
+ )
+{
+ UINTN Offset;
+ UINTN StringSize;
+ CHAR16 *ErrorStringOut;
+
+ ErrorStringOut = NULL;
+ Offset = 0;
+
+ StringSize = StrSize (HSTI_ERROR) + StrSize (ErrorCodeString) + StrSize (HSTI_PLATFORM_SECURITY_SPECIFICATION) + StrSize (ErrorCategoryString) + StrSize (ErrorString);
+ ErrorStringOut = AllocatePool (StringSize);
+
+ CopyMem (ErrorStringOut, HSTI_ERROR, StrSize (HSTI_ERROR) -1);
+ Offset += StrLen (HSTI_ERROR);
+
+ CopyMem (ErrorStringOut + Offset, ErrorCodeString, StrSize (ErrorCodeString) -1);
+ Offset += StrLen (ErrorCodeString);
+
+ CopyMem (ErrorStringOut + Offset, HSTI_PLATFORM_SECURITY_SPECIFICATION, StrSize (HSTI_PLATFORM_SECURITY_SPECIFICATION) -1);
+ Offset += StrLen (HSTI_PLATFORM_SECURITY_SPECIFICATION);
+
+ CopyMem (ErrorStringOut + Offset, ErrorCategoryString, StrSize (ErrorCategoryString) -1);
+ Offset += StrLen (ErrorCategoryString);
+
+ CopyMem (ErrorStringOut + Offset, ErrorString, StrSize (ErrorString));
+ Offset += StrLen (ErrorString);
+
+ return ErrorStringOut;
+}
+
+/**
+ Update HSTI feature data from cached results or rerun tests
+**/
+VOID
+UpdateData (
+ VOID
+ )
+{
+ ADAPTER_INFO_PLATFORM_SECURITY *Hsti;
+ UINT8 *SecurityFeatures;
+ CHAR16 *ErrorString;
+
+ if ((mSiPolicyData != NULL) && (mSiPolicyData->Hsti != NULL)) {
+
+ Hsti = mSiPolicyData->Hsti;
+
+ SecurityFeatures = (UINT8 *) (Hsti + 1);
+ SecurityFeatures = (UINT8 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+ SecurityFeatures = (UINT8 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+ ErrorString = (CHAR16 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+
+ HstiLibSetErrorString (PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,NULL,ErrorString);
+
+ } else {
+ DEBUG ((DEBUG_INFO, "0.0 Hardware Rooted Boot Integrity\n"));
+ CheckHardwareRootedBootIntegrity ();
+
+ DEBUG ((DEBUG_INFO, "0.1 Boot Firmware Media Protection (SPI)\n"));
+ CheckBootFirmwareMediaProtection ();
+
+ DEBUG ((DEBUG_INFO, "0.2 Signed Firmware Update\n"));
+ CheckSignedFirmwareUpdate ();
+
+ DEBUG ((DEBUG_INFO, "0.3 Measured Boot Enforcement\n"));
+ CheckMeasuredBootEnforcement ();
+
+ DEBUG ((DEBUG_INFO, "0.4 Integrated Device DMA Protection\n"));
+ CheckIntegratedDeviceDmaProtection ();
+
+ DEBUG ((DEBUG_INFO, "0.5 Debug Mode Disabled Verification\n"));
+ CheckDebugModeDisabled ();
+
+ DEBUG ((DEBUG_INFO, "0.6 Secure CPU Configuration\n"));
+ CheckSecureCpuConfiguration ();
+
+ DEBUG ((DEBUG_INFO, "0.7 Secure System Agent Configuration\n"));
+ CheckSecureSystemAgentConfiguration ();
+
+ DEBUG ((DEBUG_INFO, "1.0 Secure Memory Map Configuration\n"));
+ CheckSecureMemoryMapConfiguration ();
+
+ DEBUG ((DEBUG_INFO, "1.1 Secure Integrated Graphics Configuration\n"));
+ CheckSecureIntegratedGraphicsConfiguration ();
+
+ DEBUG ((DEBUG_INFO, "1.2 Secure PCH Configuration\n"));
+ CheckSecurePchConfiguration ();
+ }
+}
+
+/**
+ Dump HSTI info to setial
+
+ @param[in] HstiData - Pointer to HSTI data
+**/
+VOID
+DumpHsti (
+ IN VOID *HstiData
+ )
+{
+ ADAPTER_INFO_PLATFORM_SECURITY *Hsti;
+ UINT8 *SecurityFeatures;
+ CHAR16 *ErrorString;
+ UINTN Index;
+ CHAR16 ErrorChar;
+
+ Hsti = HstiData;
+ DEBUG ((DEBUG_INFO, "HSTI\n"));
+ DEBUG ((DEBUG_INFO, " Version - 0x%08x\n", Hsti->Version));
+ DEBUG ((DEBUG_INFO, " Role - 0x%08x\n", Hsti->Role));
+ DEBUG ((DEBUG_INFO, " ImplementationID - %S\n", Hsti->ImplementationID));
+ DEBUG ((DEBUG_INFO, " SecurityFeaturesSize - 0x%08x\n", Hsti->SecurityFeaturesSize));
+
+ SecurityFeatures = (UINT8 *) (Hsti + 1);
+ DEBUG ((DEBUG_INFO, " SecurityFeaturesRequired - "));
+ for (Index = 0; Index < Hsti->SecurityFeaturesSize; Index++) {
+ DEBUG ((DEBUG_INFO, "%02x ", SecurityFeatures[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ SecurityFeatures = (UINT8 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+ DEBUG ((DEBUG_INFO, " SecurityFeaturesImplemented - "));
+ for (Index = 0; Index < Hsti->SecurityFeaturesSize; Index++) {
+ DEBUG ((DEBUG_INFO, "%02x ", SecurityFeatures[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ SecurityFeatures = (UINT8 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+ DEBUG ((DEBUG_INFO, " SecurityFeaturesVerified - "));
+ for (Index = 0; Index < Hsti->SecurityFeaturesSize; Index++) {
+ DEBUG ((DEBUG_INFO, "%02x ", SecurityFeatures[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ ErrorString = (CHAR16 *) (SecurityFeatures + Hsti->SecurityFeaturesSize);
+ DEBUG ((DEBUG_INFO, " ErrorString - \""));
+ CopyMem (&ErrorChar, ErrorString, sizeof (ErrorChar));
+ for (; ErrorChar != 0;) {
+ DEBUG ((DEBUG_INFO, "%c", ErrorChar));
+ ErrorString++;
+ CopyMem (&ErrorChar, ErrorString, sizeof (ErrorChar));
+ }
+ DEBUG ((DEBUG_INFO, "\"\n"));
+}
+
+/**
+ Retrieve HSTI Table from AIP
+**/
+VOID
+DumpData (
+ VOID
+ )
+{
+ VOID *Hsti;
+ UINTN HstiSize;
+ EFI_STATUS Status;
+
+ Status = HstiLibGetTable (PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE, NULL, &Hsti, &HstiSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "HSTI (Role - 0x%08x) not found!\n", PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE));
+ return;
+ }
+
+ if (mSiPolicyData != NULL) {
+ mSiPolicyData->Hsti = (ADAPTER_INFO_PLATFORM_SECURITY *) Hsti;
+ mSiPolicyData->HstiSize = HstiSize;
+ }
+
+ DumpHsti (Hsti);
+}
+
+
+/**
+ Handler to gather and publish HSTI results on ReadyToBootEvent
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ InitMp ();
+ InitData ();
+ UpdateData ();
+ DumpData ();
+
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gHstiPublishCompleteProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+}
+
+/**
+ The driver's entry point.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+**/
+EFI_STATUS
+EFIAPI
+HstiSiliconDxeEntrypoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ //
+ // Locate DxeSiPolicyProtocolGuid protocol instance and assign it to a global variable
+ //
+ Status = gBS->LocateProtocol (&gDxeSiPolicyProtocolGuid, NULL, (VOID **) &mSiPolicyData);
+ if (EFI_ERROR (Status)) {
+ mSiPolicyData = NULL;
+ DEBUG ((DEBUG_ERROR,"Failed to locate DxeSiPolicyProtocolGuid Protocol\n"));
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &gImageHandle,
+ &gHstiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiCreateEventReadyToBootEx (
+ TPL_NOTIFY,
+ OnReadyToBoot,
+ NULL,
+ &Event
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.h b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.h
new file mode 100644
index 0000000000..b2b48a2152
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.h
@@ -0,0 +1,276 @@
+/** @file
+ This file contains the required header files for the HSTI Silicon DXE driver
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HSTI_SILICON_DXE_H_
+#define _HSTI_SILICON_DXE_H_
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/MpService.h>
+#include <Library/PciLib.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/UefiLib.h>
+#include <Protocol/SiPolicyProtocol.h>
+#include <IndustryStandard/Hsti.h>
+#include <Protocol/AdapterInformation.h>
+#include <Library/HstiLib.h>
+#include <HstiFeatureBit.h>
+#include <Protocol/Spi.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/HobLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchP2sbLib.h>
+
+#ifndef TPM_BASE
+#define TPM_BASE 0
+#endif
+#include <Library/Tpm2CommandLib.h>
+
+#define TPM_BASE_ADDRESS 0xfed40000
+
+//
+// Silicon
+//
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+#include <SaRegs.h>
+#include <SaAccess.h>
+#include <PchAccess.h>
+#include <MeChipset.h>
+#include <Library/PchGbeLib.h>
+#include <Library/CpuPlatformLib.h>
+
+#define SIZE_4KB 0x00001000
+#define SIZE_16KB 0x00004000
+#define SIZE_32KB 0x00008000
+#define SIZE_1MB 0x00100000
+#define SIZE_2MB 0x00200000
+#define SIZE_4MB 0x00400000
+#define SIZE_8MB 0x00800000
+#define SIZE_16MB 0x01000000
+#define SIZE_32MB 0x02000000
+#define SIZE_128MB 0x08000000
+#define SIZE_4GB 0x0000000100000000ULL
+#define BASE_4GB 0x0000000100000000ULL
+//@todo need to take this back to HstiFeatureBit.h
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_B L" SMM Code Fetch outside SMRAM detection feature is disabled\r\n"
+
+//@todo need to take this back to HstiFeatureBit.h
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_4 L"0x000A0004"
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_4 L" P2SB SBI lock not set\r\n"
+
+#define MAX_NEW_AUTHORIZATION_SIZE SHA512_DIGEST_SIZE
+
+#define HSTI_PLATFORM_NAME L"Intel(R) 9-Series v1"
+
+#pragma pack(1)
+typedef struct {
+ UINT32 Version;
+ UINT32 Role;
+ CHAR16 ImplementationID[256];
+ UINT32 SecurityFeaturesSize;
+ UINT8 SecurityFeaturesRequired[HSTI_SECURITY_FEATURE_SIZE];
+ UINT8 SecurityFeaturesImplemented[HSTI_SECURITY_FEATURE_SIZE];
+ UINT8 SecurityFeaturesVerified[HSTI_SECURITY_FEATURE_SIZE];
+ CHAR16 End;
+} ADAPTER_INFO_PLATFORM_SECURITY_STRUCT;
+#pragma pack()
+
+extern UINT8 mFeatureImplemented[HSTI_SECURITY_FEATURE_SIZE];
+extern EFI_GUID gHstiProtocolGuid;
+extern EFI_GUID gHstiPublishCompleteProtocolGuid;
+
+/**
+ Concatenate error string.
+
+ @param[in] ErrorCodeString - Error Code
+ @param[in] ErrorCategoryString - Error Category
+ @param[in] ErrorString - Error Text
+
+ @retval CHAR16 - Concatenated string.
+**/
+CHAR16 *
+EFIAPI
+BuildHstiErrorString (
+ IN CHAR16 *ErrorCodeString,
+ IN CHAR16 *ErrorCategoryString,
+ IN CHAR16 *ErrorString
+ );
+
+/**
+ Run tests for HardwareRootedBootIntegrity bit
+**/
+VOID
+CheckHardwareRootedBootIntegrity (
+ VOID
+ );
+
+/**
+ Run tests for BootFirmwareMediaProtection bit
+**/
+VOID
+CheckBootFirmwareMediaProtection (
+ VOID
+ );
+
+/**
+ Run tests for SignedFirmwareUpdate bit
+**/
+VOID
+CheckSignedFirmwareUpdate (
+ VOID
+ );
+
+/**
+ Run tests for MeasuredBootEnforcement bit
+**/
+VOID
+CheckMeasuredBootEnforcement (
+ VOID
+ );
+
+/**
+ Run tests for IntegratedDeviceDMAProtection bit
+**/
+VOID
+CheckIntegratedDeviceDmaProtection (
+ VOID
+ );
+
+/**
+ Run tests for DebugModeDisabled bit
+**/
+VOID
+CheckDebugModeDisabled (
+ VOID
+ );
+
+/**
+ Run tests for SecureCPUConfiguration bit
+**/
+VOID
+CheckSecureCpuConfiguration (
+ VOID
+ );
+
+/**
+ Run tests for SecureSystemAgentConfiguration bit
+**/
+VOID
+CheckSecureSystemAgentConfiguration (
+ VOID
+ );
+
+/**
+ Run tests for SecureMemoryMapConfiguration bit
+**/
+VOID
+CheckSecureMemoryMapConfiguration (
+ VOID
+ );
+
+/**
+ Run tests for SecureIntegratedGraphicsConfiguration bit
+**/
+VOID
+CheckSecureIntegratedGraphicsConfiguration (
+ VOID
+ );
+
+/**
+ Run tests for SecurePCHConfiguration bit
+**/
+VOID
+CheckSecurePchConfiguration (
+ VOID
+ );
+
+//
+// Help function
+//
+
+/**
+ Initialize MP Helper
+**/
+VOID
+InitMp (
+ VOID
+ );
+
+/**
+ Concatenate error string.
+
+ @retval UINTN - CpuNumber.
+**/
+UINTN
+GetCpuNumber (
+ VOID
+ );
+
+
+/**
+ Concatenate error string.
+
+ @param[in] ProcessorNumber - Processor ID
+ @param[in] Index - Index
+
+ @retval UINT64 - Msr Value.
+**/
+UINT64
+ProcessorReadMsr64 (
+ IN UINTN ProcessorNumber,
+ IN UINT32 Index
+ );
+
+/**
+ Concatenate error string.
+
+ @param[in] ProcessorNumber - Processor ID
+ @param[in] Index - Index
+ @param[out] Eax - Eax
+ @param[out] Ebx - Ebx
+ @param[out] Ecx - Ecx
+ @param[out] Edx - Edx
+**/
+VOID
+ProcessorCpuid (
+ IN UINTN ProcessorNumber,
+ IN UINT32 Index,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ );
+
+/**
+ Concatenate error string.
+
+ @param[in] Address - Address
+
+ @retval UINT64 - Value.
+**/
+UINT64
+EFIAPI
+PciRead64 (
+ IN UINTN Address
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.inf b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.inf
new file mode 100644
index 0000000000..854343da38
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/HstiSiliconDxe.inf
@@ -0,0 +1,108 @@
+## @file
+# Component description file for Hsti Silicon Driver
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HstiSiliconDxe
+ FILE_GUID = 60740CF3-D428-4500-80E6-04A5798241ED
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = HstiSiliconDxeEntrypoint
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ HstiSiliconDxe.c
+ HardwareRootedBootIntegrity.c
+ SignedFirmwareUpdate.c
+ BootFirmwareMediaProtection.c
+ MeasuredBootEnforcement.c
+ IntegratedDeviceDmaProtection.c
+ DebugModeDisabled.c
+ SecureCpuConfiguration.c
+ SecureSystemAgentConfiguration.c
+ SecureMemoryMapConfiguration.c
+ SecureIntegratedGraphicsConfiguration.c
+ SecurePCHConfiguration.c
+ MpServiceHelp.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiLib
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DebugLib
+ UefiBootServicesTableLib
+ IoLib
+ PciLib
+ HstiLib
+ PchCycleDecodingLib
+ HobLib
+ PchPcrLib
+ MmPciLib
+ PchGbeLib
+ CpuPlatformLib
+ PchP2sbLib
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid
+ gSiMemoryPlatformDataGuid ## CONSUMES
+
+[Protocols]
+ gEfiDxeSmmReadyToLockProtocolGuid ## CONSUMES
+ gHstiProtocolGuid ## PRODUCES
+ gEfiMpServiceProtocolGuid ## CONSUMES
+ gDxeSiPolicyProtocolGuid ## CONSUMES
+ gHstiPublishCompleteProtocolGuid ## PRODUCES
+
+[FixedPcd]
+ gSiPkgTokenSpaceGuid.PcdHstiIhvFeature1
+ gSiPkgTokenSpaceGuid.PcdHstiIhvFeature2
+ gSiPkgTokenSpaceGuid.PcdHstiIhvFeature3
+
+[Depex]
+ TRUE \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/IntegratedDeviceDmaProtection.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/IntegratedDeviceDmaProtection.c
new file mode 100644
index 0000000000..d45cc586ba
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/IntegratedDeviceDmaProtection.c
@@ -0,0 +1,150 @@
+/** @file
+ This file contains the tests for the IntegratedDeviceDMAProtection bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for IntegratedDeviceDMAProtection bit
+**/
+VOID
+CheckIntegratedDeviceDmaProtection (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINT32 MchBar;
+ UINT32 Vtd1;
+ UINT32 Vtd2;
+ CHAR16 *HstiErrorString;
+
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+
+ MchBar = (UINT32) MmioRead64 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_MCHBAR) & B_SA_MCHBAR_MCHBAR_MASK;
+
+ DEBUG ((DEBUG_INFO, " VTd check\n"));
+
+ DEBUG ((DEBUG_INFO, " 1. VTd supported\n"));
+
+ if ((MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_MC_CAPID0_A_OFFSET) & BIT23) != 0) {
+ DEBUG ((DEBUG_INFO, "Fail: VTd not supported\n"));
+
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_CODE_1 ,HSTI_INTEGRATED_DEVICE_DMA_PROTECTION, HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ if ((MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_MC_CAPID0_A_OFFSET) & BIT23) == 0) {
+ DEBUG ((DEBUG_INFO, " 2. VTd enabled\n"));
+
+ if (MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,2,0) + R_SA_IGD_VID) != 0xFFFF) {
+ Vtd1 = MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET);
+ if (((Vtd1 & BIT0) == 0) ||
+ ((Vtd1 & 0xfffffffe) == 0)) {
+ DEBUG ((DEBUG_INFO, "Fail: VTd not enabled\n"));
+
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_CODE_1 ,HSTI_INTEGRATED_DEVICE_DMA_PROTECTION, HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ if ((Vtd1 & 0xfffffffe) != 0) {
+ DEBUG ((DEBUG_INFO, " 3. VTd configured correctly\n"));
+
+ if ((MmioRead32 ((Vtd1 & 0xfffffffe) + 0xFF0) & BIT31) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: VTd not configured correctly\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_CODE_1 ,HSTI_INTEGRATED_DEVICE_DMA_PROTECTION, HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. VTd enabled\n"));
+
+ Vtd2 = MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET);
+ if (((Vtd2 & BIT0) == 0) ||
+ ((Vtd2 & 0xfffffffe) == 0)) {
+ DEBUG ((DEBUG_INFO, "Fail: VTd2 not enabled\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_CODE_1 ,HSTI_INTEGRATED_DEVICE_DMA_PROTECTION, HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ if ((Vtd2 & 0xfffffffe) != 0) {
+ DEBUG ((DEBUG_INFO, " 3. VTd configured correctly\n"));
+
+ if ((MmioRead32 ((Vtd2 & 0xfffffffe) + 0xFF0) & BIT31) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: VTd2 not configured correctly\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_CODE_1 ,HSTI_INTEGRATED_DEVICE_DMA_PROTECTION, HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+ }
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 0,
+ HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MeasuredBootEnforcement.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MeasuredBootEnforcement.c
new file mode 100644
index 0000000000..6d88a64060
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MeasuredBootEnforcement.c
@@ -0,0 +1,30 @@
+/** @file
+ This file contains the tests for the MeasuredBootEnforcement BIT
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for MeasuredBootEnforcement bit
+**/
+VOID
+CheckMeasuredBootEnforcement (
+ VOID
+ )
+{
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT) == 0) {
+ return;
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MpServiceHelp.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MpServiceHelp.c
new file mode 100644
index 0000000000..f1e7a8d946
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/MpServiceHelp.c
@@ -0,0 +1,216 @@
+/** @file
+ This file contains the mpservices helper functions
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+typedef struct {
+ UINT32 Index;
+ UINT64 Value;
+} AP_PRPCEDURE_ARGUMENT_READMSR;
+
+typedef struct {
+ UINT32 Index;
+ UINT32 Eax;
+ UINT32 Ebx;
+ UINT32 Ecx;
+ UINT32 Edx;
+} AP_PRPCEDURE_ARGUMENT_CPUID;
+
+EFI_MP_SERVICES_PROTOCOL *mMpService;
+UINTN mBspNumber;
+UINTN mNumberOfProcessors;
+UINTN mNumberOfEnabledProcessors;
+
+/**
+ Initialize MP Helper
+**/
+VOID
+InitMp (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "InitMp\n"));
+
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &mMpService);
+ if (EFI_ERROR (Status)) {
+ mMpService = NULL;
+ }
+
+ if (mMpService != NULL) {
+ Status = mMpService->WhoAmI (mMpService, &mBspNumber);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mMpService->GetNumberOfProcessors (mMpService, &mNumberOfProcessors, &mNumberOfEnabledProcessors);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ mBspNumber = 0;
+ mNumberOfProcessors = 1;
+ mNumberOfEnabledProcessors = 1;
+ }
+
+ DEBUG ((DEBUG_INFO, "BspNumber - 0x%x\n", mBspNumber));
+ DEBUG ((DEBUG_INFO, "NumberOfProcessors - 0x%x\n", mNumberOfProcessors));
+ DEBUG ((DEBUG_INFO, "NumberOfEnabledProcessors - 0x%x\n", mNumberOfEnabledProcessors));
+}
+
+/**
+ Concatenate error string.
+
+ @retval UINTN - CpuNumber.
+**/
+UINTN
+GetCpuNumber (
+ VOID
+ )
+{
+ return mNumberOfEnabledProcessors;
+}
+
+VOID
+EFIAPI
+ApReadMsr64 (
+ IN OUT VOID *Buffer
+ )
+{
+ AP_PRPCEDURE_ARGUMENT_READMSR *Argument;
+
+ Argument = Buffer;
+ Argument->Value = AsmReadMsr64 (Argument->Index);
+}
+
+/**
+ Concatenate error string.
+
+ @param[in, out] Buffer - Pointer to Argument
+
+**/
+VOID
+EFIAPI
+ApCpuId (
+ IN OUT VOID *Buffer
+ )
+{
+ AP_PRPCEDURE_ARGUMENT_CPUID *Argument;
+
+ Argument = Buffer;
+ AsmCpuid (Argument->Index, &Argument->Eax, &Argument->Ebx, &Argument->Ecx, &Argument->Edx);
+}
+
+/**
+ Concatenate error string.
+
+ @param[in] ProcessorNumber - Processor ID
+ @param[in] Index - Index
+
+ @retval UINT64 - Msr Value.
+**/
+UINT64
+ProcessorReadMsr64 (
+ IN UINTN ProcessorNumber,
+ IN UINT32 Index
+ )
+{
+ EFI_STATUS Status;
+ AP_PRPCEDURE_ARGUMENT_READMSR Argument;
+ UINT8 WakeApRetry;
+
+ ASSERT (ProcessorNumber < mNumberOfEnabledProcessors);
+ if (ProcessorNumber == mBspNumber) {
+ return AsmReadMsr64 (Index);
+ }
+
+ ZeroMem (&Argument, sizeof (Argument));
+ Argument.Index = Index;
+ WakeApRetry = 0;
+ do {
+ Status = mMpService->StartupThisAP (
+ mMpService,
+ ApReadMsr64,
+ ProcessorNumber,
+ NULL, // WaitEvent
+ 1000, // 1ms timeout
+ &Argument,
+ NULL // Finished
+ );
+ WakeApRetry++;
+ } while ((Status == EFI_TIMEOUT) && (WakeApRetry < 3));
+ ASSERT_EFI_ERROR (Status);
+
+ return Argument.Value;
+}
+
+/**
+ Concatenate error string.
+
+ @param[in] ProcessorNumber - Processor ID
+ @param[in] Index - Index
+ @param[out] Eax - Eax
+ @param[out] Ebx - Ebx
+ @param[out] Ecx - Ecx
+ @param[out] Edx - Edx
+**/
+VOID
+ProcessorCpuid (
+ IN UINTN ProcessorNumber,
+ IN UINT32 Index,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AP_PRPCEDURE_ARGUMENT_CPUID Argument;
+ UINT8 WakeApRetry;
+
+ ASSERT (ProcessorNumber < mNumberOfEnabledProcessors);
+ if (ProcessorNumber == mBspNumber) {
+ AsmCpuid (Index, Eax, Ebx, Ecx, Edx);
+ return;
+ }
+
+ ZeroMem (&Argument, sizeof (Argument));
+ Argument.Index = Index;
+ WakeApRetry = 0;
+ do {
+ Status = mMpService->StartupThisAP (
+ mMpService,
+ ApCpuId,
+ ProcessorNumber,
+ NULL, // WaitEvent
+ 1000, // 1ms timeout
+ &Argument,
+ NULL // Finished
+ );
+ WakeApRetry++;
+ } while ((Status == EFI_TIMEOUT) && (WakeApRetry < 3));
+ ASSERT_EFI_ERROR (Status);
+
+ if (Eax != NULL) {
+ *Eax = Argument.Eax;
+ }
+ if (Ebx != NULL) {
+ *Ebx = Argument.Ebx;
+ }
+ if (Ecx != NULL) {
+ *Ecx = Argument.Ecx;
+ }
+ if (Edx != NULL) {
+ *Edx = Argument.Edx;
+ }
+
+ return;
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureCpuConfiguration.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureCpuConfiguration.c
new file mode 100644
index 0000000000..8abb3caf1f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureCpuConfiguration.c
@@ -0,0 +1,344 @@
+/** @file
+ This file contains the tests for the SecureCPUConfiguration bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for SecureCPUConfiguration bit
+**/
+VOID
+CheckSecureCpuConfiguration (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINTN CpuNumber;
+ UINTN CpuIndex;
+ CPUID_VERSION_INFO_ECX Ecx;
+ UINT8 SramC;
+ UINT32 TsegMB;
+ UINT32 Bgsm;
+ UINT64 SmrrBase;
+ UINT64 SmrrMask;
+ UINT64 MasterSmrrBase;
+ UINT64 MasterSmrrMask;
+ CHAR16 *HstiErrorString;
+ UINT64 SmmFeatureControl;
+ MSR_IA32_FEATURE_CONTROL_REGISTER Ia32FeatureControlMsr;
+ MSR_IA32_MTRRCAP_REGISTER MtrrCapMsr;
+
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_SECURE_CPU_CONFIGURATION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+
+ DEBUG ((DEBUG_INFO, " Table 3-1. CPU Security Configuration\n"));
+
+ CpuNumber = GetCpuNumber ();
+ for (CpuIndex = 0; CpuIndex < CpuNumber; CpuIndex++) {
+ DEBUG ((DEBUG_INFO, " [CPU - 0x%x]\n", CpuIndex));
+
+ DEBUG ((DEBUG_INFO, " 1. Microcode Update Revision\n"));
+ if ((ProcessorReadMsr64 (CpuIndex, MSR_IA32_BIOS_SIGN_ID) & 0xFFFFFFFF00000000) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_1 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. Sample Part \n"));
+
+ if ((ProcessorReadMsr64 (CpuIndex, MSR_PLATFORM_INFO) & BIT27) != 0) {
+ DEBUG ((DEBUG_INFO, "Fail: This is a sample part\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_2 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 3. IA32_FEATURE_CONTROL MSR Lock\n"));
+
+ Ia32FeatureControlMsr.Uint64 = ProcessorReadMsr64 (CpuIndex, MSR_IA32_FEATURE_CONTROL);
+ if (Ia32FeatureControlMsr.Bits.Lock == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: This is a sample part\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_3 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_3);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 4. SMM_FEATURE_CONTROL MSR Lock\n"));
+
+ SmmFeatureControl = ProcessorReadMsr64 (CpuIndex, MSR_SMM_FEATURE_CONTROL);
+
+ DEBUG ((DEBUG_INFO, " 4. SMM_CODE_CHK_EN TEST\n"));
+
+ if ((SmmFeatureControl & B_SMM_CODE_CHK_EN) == 0) {
+
+ DEBUG ((DEBUG_INFO, "Fail: SMM Code Fetch outside SMRAM dectect feature disabled\n"));
+
+ HstiErrorString = BuildHstiErrorString(HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_4 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_B);
+ Status = HstiLibAppendErrorString(
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool(HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " SMM_FEATURE_CONTROL MSR Lock\n"));
+
+ if ((SmmFeatureControl & B_SMM_FEATURE_CONTROL_LOCK) == 0) {
+
+ DEBUG ((DEBUG_INFO, "Fail: Smm feature control msr not locked\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_4 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_4);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 5. FEATURE_CONFIG MSR Lock\n"));
+
+ ProcessorCpuid (CpuIndex, CPUID_VERSION_INFO, NULL, NULL, &Ecx.Uint32, NULL);
+ if (Ecx.Bits.AESNI == 1) {
+ if ((ProcessorReadMsr64 (CpuIndex, MSR_IA32_FEATURE_CONFIG) & B_IA32_FEATURE_CONFIG_LOCK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: Feature control msr not locked\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_5 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_5);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, " Table 7-4. SMM Security Configuration\n"));
+
+ DEBUG ((DEBUG_INFO, " 1. SMRAMC\n"));
+
+ SramC = MmioRead8 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_SMRAMC);
+ if ((SramC & B_SA_SMRAMC_D_LCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: SMRAMC not locked\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_8 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_8);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. TSEGMB\n"));
+
+ TsegMB = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_TSEGMB);
+ if ((TsegMB & B_SA_TSEGMB_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: TSEGMB not locked\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_8 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_8);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 3. TSEGMB Alignment\n"));
+
+ if (((TsegMB & B_SA_TSEGMB_TSEGMB_MASK) & (LShiftU64 (1,20) - 1)) != 0) {
+ DEBUG ((DEBUG_INFO, "Fail: TSEGMB not size aligned, TSEG size: 0x%x\n",(LShiftU64 (1,20) - 1)));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_9 ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_9);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ MasterSmrrBase = 0;
+ MasterSmrrMask = 0;
+ for (CpuIndex = 0; CpuIndex < CpuNumber; CpuIndex++) {
+ DEBUG ((DEBUG_INFO, " [CPU - 0x%x]\n", CpuIndex));
+
+ DEBUG ((DEBUG_INFO, " 4. SMRR1 are supported\n"));
+
+ MtrrCapMsr.Uint64 = ProcessorReadMsr64 (CpuIndex, MSR_IA32_MTRRCAP);
+ if (MtrrCapMsr.Bits.SMRR == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: SMRR1 not supported\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_A ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ } else {
+ DEBUG ((DEBUG_INFO, " 5. SMRR1 programmed consistently on all cores\n"));
+
+ SmrrBase = ProcessorReadMsr64 (CpuIndex, MSR_IA32_SMRR_PHYSBASE);
+ SmrrMask = ProcessorReadMsr64 (CpuIndex, MSR_IA32_SMRR_PHYSMASK);
+
+ if (CpuIndex == 0) {
+ MasterSmrrBase = SmrrBase;
+ MasterSmrrMask = SmrrMask;
+ } else {
+ if ((SmrrBase != MasterSmrrBase) || (SmrrMask != MasterSmrrMask)) {
+ DEBUG ((DEBUG_INFO, "Fail: SMRR1 not programmed consistently across all cores\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_A ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, " 6. SMRR1 enabled/correct\n"));
+
+ if (((SmrrMask & BIT11) == 0x0) ||
+ ((SmrrMask & BIT9) != 0x0) ||
+ ((SmrrBase & 0x7) != 0x6)) {
+ DEBUG ((DEBUG_INFO, "Fail: SMRR1 not enabled/correct\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_A ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 7. SMRR1 and TSEGMB match\n"));
+
+ DEBUG ((DEBUG_INFO, "SMRR: 0x%08x - 0x%08x\n", SmrrBase & (SmrrMask & 0xFFFFF000), (UINT32) (~(SmrrMask & 0xFFFFF000) + 1)));
+ DEBUG ((DEBUG_INFO, "TSEGMB: 0x%08x\n", TsegMB & B_SA_TSEGMB_TSEGMB_MASK));
+
+ if ((SmrrBase & (SmrrMask & 0xFFFFF000)) != (TsegMB & B_SA_TSEGMB_TSEGMB_MASK)) {
+ DEBUG ((DEBUG_INFO, "Fail: SMRR1 != TSEGMB\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_A ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 8. SMRR1 size\n"));
+ Bgsm = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_BGSM);
+
+ if ((UINT32) (~(SmrrMask & 0xFFFFF000) + 1) !=
+ ((Bgsm & B_SA_BGSM_BGSM_MASK) - (TsegMB & B_SA_TSEGMB_TSEGMB_MASK))) {
+ DEBUG ((DEBUG_INFO, "Fail: SMRR1 size != BGSM-TSEGMB\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_A ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 9. SMRR1 work\n"));
+
+ if (MmioRead32 (SmrrBase & SmrrMask) != 0xFFFFFFFF) {
+ DEBUG ((DEBUG_INFO, "Fail: SMRR1 not working, read succeeded\n"));
+
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_A ,HSTI_CPU_SECURITY_CONFIGURATION, HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_A);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+ }
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 0,
+ HSTI_BYTE0_SECURE_CPU_CONFIGURATION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureIntegratedGraphicsConfiguration.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureIntegratedGraphicsConfiguration.c
new file mode 100644
index 0000000000..c70ac41cf6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureIntegratedGraphicsConfiguration.c
@@ -0,0 +1,221 @@
+/** @file
+ This file contains the tests for the SecureIntegratedGraphics bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for SecureIntegratedGraphicsConfiguration bit
+**/
+VOID
+CheckSecureIntegratedGraphicsConfiguration (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINT32 MchBar;
+ UINT16 Ggc;
+ UINT32 Pavpc;
+ UINT32 Bdsm;
+ UINT32 Bgsm;
+ UINT32 Tolud;
+ UINT32 GsmSize;
+ UINT32 DsmSize;
+ UINT32 Data32;
+ UINT32 PcmBase;
+ CHAR16 *HstiErrorString;
+
+ if ((mFeatureImplemented[1] & HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+
+ MchBar = (UINT32) MmioRead64 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_MCHBAR) & B_SA_MCHBAR_MCHBAR_MASK;
+
+ DEBUG ((DEBUG_INFO, " Table 3-9. Processor Graphics Security Configuration\n"));
+
+ DEBUG ((DEBUG_INFO, " 1. GGC\n"));
+
+ Ggc = MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_GGC);
+ if ((Ggc & B_SA_GGC_GGCLCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: GGCLCK bit not set\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_1 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. PAVPC\n"));
+
+ Pavpc = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_PAVPC);
+ if ((Pavpc & B_SA_PAVPC_PAVPLCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: PAVPLCK bit not set\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_1 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 3. BDSM\n"));
+
+ Bdsm = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_BDSM);
+ if ((Bdsm & B_SA_BDSM_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: BDSM not locked \n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_1 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 4. BGSM\n"));
+
+ Bgsm = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_BGSM);
+ if ((Bdsm & B_SA_BGSM_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: BGSM not locked \n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_1 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 5. PAVP Settings\n"));
+
+ Data32 = MmioRead32 (MchBar + 0x5500);
+ if ((Data32 & BIT0) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: LockPAVP Settings not set \n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_1 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 6. IGD stolen memory consistency\n"));
+
+ Tolud = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_TOLUD);
+
+ switch ((Ggc & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET) {
+ case V_SKL_SA_GGC_GGMS_2MB:
+ GsmSize = SIZE_2MB;
+ break;
+ case V_SKL_SA_GGC_GGMS_4MB:
+ GsmSize = SIZE_4MB;
+ break;
+ case V_SKL_SA_GGC_GGMS_8MB:
+ GsmSize = SIZE_8MB;
+ break;
+ default:
+ GsmSize = 0;
+ break;
+ }
+
+ DsmSize = ((Ggc & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) * SIZE_32MB;
+
+ DEBUG ((DEBUG_INFO, "DSM: 0x%08x - 0x%08x\n", Bdsm & B_SA_BDSM_BDSM_MASK, DsmSize));
+ DEBUG ((DEBUG_INFO, "GSM: 0x%08x - 0x%08x\n", Bgsm & B_SA_BGSM_BGSM_MASK, GsmSize));
+ DEBUG ((DEBUG_INFO, "TOLUD: 0x%08x\n", Tolud & B_SA_TOLUD_TOLUD_MASK));
+
+ if ((Bgsm & B_SA_BGSM_BGSM_MASK) != (Bdsm & B_SA_BDSM_BDSM_MASK) - GsmSize) {
+ DEBUG ((DEBUG_INFO, "Fail: BGSM: 0x%x != %x - %x \n",(Bgsm & B_SA_BGSM_BGSM_MASK),(Bdsm & B_SA_BDSM_BDSM_MASK),GsmSize));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_2 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ if ((Bdsm & B_SA_BDSM_BDSM_MASK) != (Tolud & B_SA_TOLUD_TOLUD_MASK) - DsmSize) {
+ DEBUG ((DEBUG_INFO, "Fail: BDSM: 0x%x != %x - %x \n",(Bdsm & B_SA_BDSM_BDSM_MASK),(Tolud & B_SA_TOLUD_TOLUD_MASK),DsmSize));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_2 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 7. Reserved Check\n"));
+ if ((Pavpc & B_SA_PAVPC_PCME_MASK) != 0) {
+ PcmBase = Pavpc & B_SA_PAVPC_PCMBASE_MASK;
+ DEBUG ((DEBUG_INFO, "PCMBASE: 0x%08x - 0x%08x\n", PcmBase, SIZE_1MB));
+ if ((PcmBase < (Bdsm & B_SA_BDSM_BDSM_MASK)) ||
+ (PcmBase > (Tolud & B_SA_TOLUD_TOLUD_MASK)) ||
+ ((PcmBase + SIZE_1MB) < (Bdsm & B_SA_BDSM_BDSM_MASK)) ||
+ ((PcmBase + SIZE_1MB) > (Tolud & B_SA_TOLUD_TOLUD_MASK))) {
+ DEBUG ((DEBUG_INFO, "Fail: Graphics security reserved check failed \n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_3 ,HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_3);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 1,
+ HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureMemoryMapConfiguration.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureMemoryMapConfiguration.c
new file mode 100644
index 0000000000..00dd3092a1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureMemoryMapConfiguration.c
@@ -0,0 +1,752 @@
+/** @file
+ This file contains the tests for the SecureMemoryMapConfiguration bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+typedef struct {
+ UINT64 Base;
+ UINT64 End;
+} MEMORY_RANGE;
+
+typedef enum {
+ LockableMemoryRangeLtSpace,
+ LockableMemoryRangeHighBios,
+ LockableMemoryRangeLowDram,
+ LockableMemoryRangeHighDram,
+ LockableMemoryRangeMchBar,
+ LockableMemoryRangeDmiBar,
+ LockableMemoryRangePxpEpBar,
+ LockableMemoryRangeGfxVtBar,
+ LockableMemoryRangeVtdPvc0Bar,
+ LockableMemoryRangeGdxcBar,
+ LockableMemoryRangeEdramBar,
+ LockableMemoryRangeCpuRsvd1Bar,
+ LockableMemoryRangeCpuRsvd2Bar,
+ LockableMemoryRangeMax,
+} LOCKABLE_MEMORY_RAMGE;
+
+MEMORY_RANGE mLockableMemoryRange[LockableMemoryRangeMax] = {
+ // 1. LT space (0xFED20000 - 0xFED7FFFF)
+ {0xFED20000, 0xFED7FFFF},
+ // 2. High BIOS
+ {0x0, SIZE_4GB - 1},
+ // 3. Low DRAM (0 - TOLUD)
+ {0x0, 0},
+ // 4. High DRAM (4GB - TOUUD)
+ {SIZE_4GB, 0},
+ // 5. MCHBAR
+ {0, 0},
+ // 6. DMIBAR
+ {0, 0},
+ // 7. PXPEPBAR
+ {0, 0},
+ // 8. GFXVTBAR
+ {0, 0},
+ // 9. VTDPVC0BAR
+ {0, 0},
+ // 10. GDXCBAR
+ {0, 0},
+ // 11. EDRAMBAR (MCHBAR + 0x5408)
+ {0, 0},
+ // 12. CPU Reserved space: 0xFEB00000 to 0xFEB0FFFF
+ {0xFEB00000, 0xFEB0FFFF},
+ // 13. CPU Reserved space: 0xFEB80000 to 0xFEB8FFFF
+ {0xFEB80000, 0xFEB8FFFF},
+};
+
+typedef enum {
+ NonLockableMemoryRangeMBASE0,
+ NonLockableMemoryRangePMBASE0,
+ NonLockableMemoryRangePMBASEU0,
+ NonLockableMemoryRangeMBASE1,
+ NonLockableMemoryRangePMBASE1,
+ NonLockableMemoryRangePMBASEU1,
+ NonLockableMemoryRangeMBASE2,
+ NonLockableMemoryRangePMBASE2,
+ NonLockableMemoryRangePMBASEU2,
+ NonLockableMemoryRangeGTTMMADR,
+ NonLockableMemoryRangeGMADR,
+ NonLockableMemoryRangeTMBAR,
+ NonLockableMemoryRangeABAR,
+ NonLockableMemoryRangeSBREG_BAR,
+ NonLockableMemoryRangePWRMBASE,
+ NonLockableMemoryRangeSPI_BAR0,
+ NonLockableMemoryRangeMax,
+} NONLOCKABLE_MEMORY_RAMGE;
+
+MEMORY_RANGE mNonLockableMemoryRange[NonLockableMemoryRangeMax] = {
+ {0, 0},
+// 1. Local Apic for each CPU thread (IA32_APICBASE MSR 0x1B)
+// 2. MBASE0, (PEG) BDF 0:1:0 + 0x20
+// 3. PMBASE0, (PEG) BDF 0:1:0 + 0x24 LOW
+// BDF 0:1:1 + 0x28 HIGH
+// 4. MBASE1, (PEG) BDF 0:1:1 + 0x20
+// 5. PMBASE1, (PEG) BDF 0:1:1 + 0x24 LOW
+// BDF 0:1:1 + 0x28 HIGH
+// 6. MBASE2, (PEG) BDF 0:1:2 + 0x20
+// 7. PMBASE2, (PEG) BDF 0:1:2 + 0x24 LOW
+// BDF 0:1:1 + 0x28 HIGH
+// 8. GTTMMADR, BDF 0:2:0 + 0x10
+// 9. GMADR, BDF 0:2:0 + 0x18 (Need to account for MSAC)
+// 10. TMBAR, BDF 0:4:0 + 0x10 (if Device 4 is enabled in BDF 0:0:0 + 0x54[7])
+// 11. ABAR, BDF 0:31:2 + 0x24
+// 12. SBREG_BAR (BDF 0:31:1 + 0x10)
+// 13. PWRMBASE (BDF 0:31:2 + 0x48)
+// 14. SPI_BAR0 (BDF 0:31:5 + 0x10)
+};
+
+/**
+ Check for overlaps in single range array
+
+ @param[in] Range - Pointer to Range array
+ @param[in] Count - Number of Enties
+
+ @retval BOOLEAN - Overlap Exists
+**/
+BOOLEAN
+CheckOverlap (
+ IN MEMORY_RANGE *Range,
+ IN UINTN Count
+ )
+{
+ UINTN Index;
+ UINTN SubIndex;
+
+ for (Index = 0; Index < Count - 1; Index++) {
+ if ((Range[Index].Base == 0) && (Range[Index].End == 0)) {
+ continue;
+ }
+ for (SubIndex = Index + 1; SubIndex < Count; SubIndex++) {
+ if ((Range[SubIndex].Base == 0) && (Range[SubIndex].End == 0)) {
+ continue;
+ }
+ if (((Range[Index].Base >= Range[SubIndex].Base) && (Range[Index].Base <= Range[SubIndex].End)) ||
+ ((Range[SubIndex].Base >= Range[Index].Base) && (Range[SubIndex].Base <= Range[Index].End))) {
+ DEBUG ((DEBUG_ERROR, "OVERLAP: \n"));
+ DEBUG ((DEBUG_ERROR, " 0x%016lx - 0x%016lx\n", Range[Index].Base, Range[Index].End));
+ DEBUG ((DEBUG_ERROR, " 0x%016lx - 0x%016lx\n", Range[SubIndex].Base, Range[SubIndex].End));
+ return TRUE;
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "CheckOverlap: PASS\n"));
+ return FALSE;
+}
+
+/**
+ Check for overlaps between two arrays of memory ranges
+
+ @param[in] Range1 - Pointer to Range1 array
+ @param[in] Count1 - Number of Enties
+ @param[in] Range2 - Pointer to Range2 array
+ @param[in] Count2 - Number of Enties
+
+ @retval BOOLEAN - Overlap Exists
+**/
+BOOLEAN
+CheckOverlap2 (
+ IN MEMORY_RANGE *Range1,
+ IN UINTN Count1,
+ IN MEMORY_RANGE *Range2,
+ IN UINTN Count2
+ )
+{
+ UINTN Index1;
+ UINTN Index2;
+
+ for (Index1 = 0; Index1 < Count1; Index1++) {
+ if ((Range1[Index1].Base == 0) && (Range1[Index1].End == 0)) {
+ continue;
+ }
+ for (Index2 = 0; Index2 < Count2; Index2++) {
+ if ((Range2[Index2].Base == 0) && (Range2[Index2].End == 0)) {
+ continue;
+ }
+ if (((Range1[Index1].Base >= Range2[Index2].Base) && (Range1[Index1].Base <= Range2[Index2].End)) ||
+ ((Range2[Index2].Base >= Range1[Index1].Base) && (Range2[Index2].Base <= Range1[Index1].End))) {
+ DEBUG ((DEBUG_ERROR, "OVERLAP2: \n"));
+ DEBUG ((DEBUG_ERROR, " 0x%016lx - 0x%016lx\n", Range1[Index1].Base, Range1[Index1].End));
+ DEBUG ((DEBUG_ERROR, " 0x%016lx - 0x%016lx\n", Range2[Index2].Base, Range2[Index2].End));
+ return TRUE;
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "CheckOverlap2: PASS\n"));
+ return FALSE;
+}
+
+/**
+ Dumps Ranges to Serial
+
+ @param[in] Range - Pointer to Range array
+ @param[in] Count - Number of Enties
+
+**/
+VOID
+DumpRange (
+ IN MEMORY_RANGE *Range,
+ IN UINTN Count
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < Count; Index ++) {
+ DEBUG ((DEBUG_INFO, " [%02d] 0x%016lx - 0x%016lx\n", Index, Range[Index].Base, Range[Index].End));
+ }
+}
+//
+// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.
+// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range
+// won't overlap with SMRAM range, and trusted.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr;
+
+/**
+ Acquire PCH spi mmio address.
+ It is not expected for this BAR0 to change because the SPI device is hidden
+ from the OS for SKL PCH LP/H B stepping and above (refer to section 3.5.1),
+ but 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.
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ VOID
+ )
+{
+ UINT32 SpiBar0;
+ UINTN PchSpiBase;
+
+ //
+ // Init PCH spi reserved MMIO address.
+ //
+ mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
+
+ PchSpiBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ //
+ // Save original SPI physical MMIO address
+ //
+ SpiBar0 = MmioRead32 (PchSpiBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+
+ if (SpiBar0 != mSpiResvMmioAddr) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ MmioAnd8 (PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (PchSpiBase + R_PCH_SPI_BAR0, mSpiResvMmioAddr);
+ MmioOr8 (PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+ //
+ // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg.
+ //
+ return mSpiResvMmioAddr;
+}
+
+/**
+ Release pch spi mmio address. Do nothing.
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ VOID
+ )
+{
+}
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+GetRegionAddress (
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ )
+{
+ UINTN PchSpiBar0;
+ UINT32 ReadValue;
+
+ if (FlashRegionType >= FlashRegionMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FlashRegionType == FlashRegionAll) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PchSpiBar0 = AcquireSpiBar0 ();
+ ReadValue = MmioRead32 (PchSpiBar0 + (R_PCH_SPI_FREG0_FLASHD + (S_PCH_SPI_FREGX * ((UINT32) FlashRegionType))));
+ ReleaseSpiBar0 ();
+
+ //
+ // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h
+ //
+ if (ReadValue == B_PCH_SPI_FREGX_BASE_MASK) {
+ return EFI_DEVICE_ERROR;
+ }
+ *BaseAddress = ((ReadValue & B_PCH_SPI_FREGX_BASE_MASK) >> N_PCH_SPI_FREGX_BASE) <<
+ N_PCH_SPI_FREGX_BASE_REPR;
+ //
+ // Region limit address Bits[11:0] are assumed to be FFFh
+ //
+ *RegionSize = ((((ReadValue & B_PCH_SPI_FREGX_LIMIT_MASK) >> N_PCH_SPI_FREGX_LIMIT) + 1) <<
+ N_PCH_SPI_FREGX_LIMIT_REPR) - *BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Run tests for SecureMemoryMapConfiguration bit
+**/
+VOID
+CheckSecureMemoryMapConfiguration (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINT32 MchBar;
+ UINT32 Dpr;
+ UINT32 MeSegMask;
+ UINT64 RemapBase;
+ UINT64 RemapLimit;
+ UINT32 Tom;
+ UINT32 Touud;
+ UINT32 Tolud;
+ UINT64 Data64;
+ UINT32 ApertureSize;
+ UINT8 Msac;
+ CHAR16 *HstiErrorString;
+ UINT32 BarRead;
+ UINT16 VendorIdRead;
+ UINTN PchSpiBase;
+ UINT32 PwrmBase;
+ UINT32 AbarSize;
+ UINT32 BaseAddress;
+ UINT32 RegionSize;
+
+ if ((mFeatureImplemented[1] & HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+
+ MchBar = (UINT32) MmioRead64 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_MCHBAR) & B_SA_MCHBAR_MCHBAR_MASK;
+
+ DEBUG ((DEBUG_INFO, " Table 3-3. Memory Map Secure Configuration\n"));
+
+ DEBUG ((DEBUG_INFO, " 1. DPR\n"));
+
+ Dpr = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_DPR);
+
+ if ((Dpr & B_SA_DPR_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: DPR not locked\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. MESEG\n"));
+ MeSegMask = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_MESEG_MASK);
+
+ if ((MeSegMask & B_SA_MESEG_MASK_MELCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: MESEG not locked\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 3. REMAPBASE\n"));
+
+ RemapBase = MmioRead64 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_REMAPBASE);
+
+ if ((RemapBase & B_SA_REMAPBASE_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: REMAPBASE lock not set\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 4. REMAPLIMIT\n"));
+ RemapLimit = MmioRead64 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_REMAPLIMIT);
+
+ if ((RemapLimit & B_SA_REMAPLIMIT_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: REMAPLIMIT lock not set\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 5. Top Of Memory (TOM)\n"));
+ Tom = MmioRead32 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_TOM);
+
+ if ((Tom & B_SA_TOM_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: TOM lock not set\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 6. Top Of Upper Usable DRAM (TOUUD)\n"));
+ Touud = MmioRead32 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_TOUUD);
+
+ if ((Touud & B_SA_TOUUD_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: TOUUD lock not set\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 7. Top Of Lower Usable Memory (TOLUD)\n"));
+ Tolud =MmioRead32 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_TOLUD);
+
+ if ((Touud & B_SA_TOLUD_LOCK_MASK) == 0) {
+ DEBUG ((DEBUG_INFO, "Fail: TOLUD lock not set\n"));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 8. Lockable/fixed memory ranges overlap\n"));
+
+ //
+ // Locate BIOS region size to update High bios base address
+ //
+ GetRegionAddress (FlashRegionBios, &BaseAddress, &RegionSize);
+ DEBUG ((DEBUG_INFO, "Bios Region Size %x:\n", RegionSize));
+ mLockableMemoryRange[LockableMemoryRangeHighBios].Base = SIZE_4GB - RegionSize;
+ mLockableMemoryRange[LockableMemoryRangeLowDram].End = (MmioRead32 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_TOLUD) & B_SA_TOLUD_TOLUD_MASK) - 1;
+
+ mLockableMemoryRange[LockableMemoryRangeHighDram].End = (MmioRead64 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_TOUUD) & B_SA_TOUUD_TOUUD_MASK) - 1;
+
+ mLockableMemoryRange[LockableMemoryRangeMchBar].Base = MmioRead64 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_MCHBAR) & B_SA_MCHBAR_MCHBAR_MASK;
+ mLockableMemoryRange[LockableMemoryRangeMchBar].End = mLockableMemoryRange[LockableMemoryRangeMchBar].Base + SIZE_32KB - 1;
+
+ mLockableMemoryRange[LockableMemoryRangeDmiBar].Base = MmioRead64 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_DMIBAR) & B_SA_DMIBAR_DMIBAR_MASK;
+ mLockableMemoryRange[LockableMemoryRangeDmiBar].End = mLockableMemoryRange[LockableMemoryRangeDmiBar].Base + SIZE_4KB - 1;
+ mLockableMemoryRange[LockableMemoryRangePxpEpBar].Base = MmioRead64 (MmPciBase (0,SA_MC_DEV,SA_MC_FUN) + R_SA_PXPEPBAR) & B_SA_PXPEPBAR_PXPEPBAR_MASK;
+ mLockableMemoryRange[LockableMemoryRangePxpEpBar].End = mLockableMemoryRange[LockableMemoryRangePxpEpBar].Base + SIZE_4KB - 1;
+ Data64 = MmioRead64 (MchBar + 0x5400);
+ if ((Data64 & BIT0) != 0) {
+ mLockableMemoryRange[LockableMemoryRangeGfxVtBar].Base = Data64 & 0x7FFFFFF000;
+ mLockableMemoryRange[LockableMemoryRangeGfxVtBar].End = mLockableMemoryRange[LockableMemoryRangeGfxVtBar].Base + 0x1000 - 1;
+ }
+ Data64 = MmioRead64 (MchBar + 0x5410);
+ if ((Data64 & BIT0) != 0) {
+ mLockableMemoryRange[LockableMemoryRangeVtdPvc0Bar].Base = Data64 & 0x7FFFFFF000;
+ mLockableMemoryRange[LockableMemoryRangeVtdPvc0Bar].End = mLockableMemoryRange[LockableMemoryRangeVtdPvc0Bar].Base + 0x1000 - 1;
+ }
+ Data64 = MmioRead64 (MchBar + 0x5420);
+ if ((Data64 & BIT0) != 0) {
+ mLockableMemoryRange[LockableMemoryRangeGdxcBar].Base = Data64 & 0x7FFFFFF000;
+ mLockableMemoryRange[LockableMemoryRangeGdxcBar].End = mLockableMemoryRange[LockableMemoryRangeGdxcBar].Base + 0x1000 - 1;
+ }
+ Data64 = MmioRead64 (MchBar + 0x5408);
+ if ((Data64 & BIT0) != 0) {
+ mLockableMemoryRange[LockableMemoryRangeEdramBar].Base = Data64 & 0x7FFFFFC000;
+ mLockableMemoryRange[LockableMemoryRangeEdramBar].End = mLockableMemoryRange[LockableMemoryRangeEdramBar].Base + 0x4000 - 1;
+ }
+
+ DEBUG ((DEBUG_INFO, "Lockable memory ranges:\n"));
+ DumpRange (mLockableMemoryRange, LockableMemoryRangeMax);
+ if (CheckOverlap (mLockableMemoryRange, LockableMemoryRangeMax) || EFI_ERROR (Status)) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_2 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 9. Non lockable memory ranges overlap\n"));
+
+ if (MmioRead32 (MmPciBase (0,0,0) + 0x54) & BIT3) {
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE0].Base = LShiftU64 ((MmioRead16 (MmPciBase (0,SA_PEG10_DEV_NUM,SA_PEG10_FUN_NUM) + 0x20) & 0xFFF0),16);
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE0].End = LShiftU64 ((MmioRead16 (MmPciBase (0,SA_PEG10_DEV_NUM,SA_PEG10_FUN_NUM) + 0x22) & 0xFFF0),16);
+
+ BarRead = MmioRead16 (MmPciBase (0,SA_PEG10_DEV_NUM,SA_PEG10_FUN_NUM) + 0x24);
+ if ((BarRead & 0xF) != 0) {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].Base = LShiftU64 ((BarRead & 0xFFF0),16) + LShiftU64 ((MmioRead32 (MmPciBase (0,SA_PEG10_DEV_NUM,SA_PEG10_FUN_NUM) + 0x28)),32);
+ } else {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].Base = LShiftU64 ((BarRead & 0xFFF0),16);
+ }
+
+ BarRead = MmioRead16 (MmPciBase (0,SA_PEG10_DEV_NUM,SA_PEG10_FUN_NUM) + 0x26);
+ if ((BarRead & 0xF) != 0) {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].End = LShiftU64 ((BarRead & 0xFFF0),16) + LShiftU64 ((MmioRead32 (MmPciBase (0,SA_PEG10_DEV_NUM,SA_PEG10_FUN_NUM) + 0x2C)),32);
+ } else {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].End = LShiftU64 ((BarRead & 0xFFF0),16);
+ }
+ }
+
+ //
+ // Check to make sure that if PEG0 is enabled but nothing is connected that we ignore these ranges
+ //
+ if(mNonLockableMemoryRange[NonLockableMemoryRangeMBASE0].End < mNonLockableMemoryRange[NonLockableMemoryRangeMBASE0].Base)
+ {
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE0].Base = 0;
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE0].End = 0;
+ }
+ if(mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].End < mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].Base)
+ {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].Base = 0;
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE0].End = 0;
+ }
+
+ if (MmioRead32 (MmPciBase (0,0,0) + 0x54) & BIT2) {
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE1].Base = LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG11_DEV_NUM,SA_PEG11_FUN_NUM) + 0x20) & 0xFFF0),16);
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE1].End = LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG11_DEV_NUM,SA_PEG11_FUN_NUM) + 0x22) & 0xFFF0),16);
+
+ BarRead = MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG11_DEV_NUM,SA_PEG11_FUN_NUM) + 0x24);
+
+ if ((BarRead & 0xF) != 0) {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].Base = LShiftU64 ((BarRead & 0xFFF0),16) + LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG11_DEV_NUM,SA_PEG11_FUN_NUM) + 0x28)),32);
+ } else {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].Base = LShiftU64 ((BarRead & 0xFFF0),16);
+ }
+
+ BarRead = MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG11_DEV_NUM,SA_PEG11_FUN_NUM) + 0x26);
+ if ((BarRead & 0xF) != 0) {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].End = LShiftU64 ((BarRead & 0xFFF0),16) + LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG11_DEV_NUM,SA_PEG11_FUN_NUM) + 0x2C)),32);
+ } else {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].End = LShiftU64 ((BarRead & 0xFFF0),16);
+ }
+ }
+
+ //
+ // Check to make sure that if PEG1 is enabled but nothing is connected that we ignore these ranges
+ //
+ if(mNonLockableMemoryRange[NonLockableMemoryRangeMBASE1].End < mNonLockableMemoryRange[NonLockableMemoryRangeMBASE1].Base)
+ {
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE1].Base = 0;
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE1].End = 0;
+ }
+ if(mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].End < mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].Base)
+ {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].Base = 0;
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE1].End = 0;
+ }
+
+ if (MmioRead32 (MmPciBase (0,0,0) + 0x54) & BIT1) {
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE2].Base = LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG12_DEV_NUM,SA_PEG12_FUN_NUM) + 0x20) & 0xFFF0),16);
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE2].End = LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG12_DEV_NUM,SA_PEG12_FUN_NUM) + 0x22) & 0xFFF0),16);
+
+ BarRead = MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG12_DEV_NUM,SA_PEG12_FUN_NUM) + 0x24);
+ if ((BarRead & 0xF) != 0) {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].Base = LShiftU64 ((BarRead & 0xFFF0),16) + LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG12_DEV_NUM,SA_PEG12_FUN_NUM) + 0x28)),32);
+
+ } else {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].Base = LShiftU64 ((BarRead & 0xFFF0),16);
+ }
+
+ BarRead = MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG12_DEV_NUM,SA_PEG12_FUN_NUM) + 0x26);
+
+ if ((BarRead & 0xF) != 0) {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].End = LShiftU64 ((BarRead & 0xFFF0),16) + LShiftU64 ((MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_PEG12_DEV_NUM,SA_PEG12_FUN_NUM) + 0x2C)),32);
+ } else {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].End = LShiftU64 ((BarRead & 0xFFF0),16);
+ }
+ }
+
+ //
+ // Check to make sure that if PEG2 is enabled but nothing is connected that we ignore these ranges
+ //
+ if(mNonLockableMemoryRange[NonLockableMemoryRangeMBASE2].End < mNonLockableMemoryRange[NonLockableMemoryRangeMBASE2].Base)
+ {
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE2].Base = 0;
+ mNonLockableMemoryRange[NonLockableMemoryRangeMBASE2].End = 0;
+ }
+ if(mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].End < mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].Base)
+ {
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].Base = 0;
+ mNonLockableMemoryRange[NonLockableMemoryRangePMBASE2].End = 0;
+ }
+
+ if (MmioRead32 (MmPciBase (0,0,0) + 0x54) & BIT4) {
+ mNonLockableMemoryRange[NonLockableMemoryRangeGTTMMADR].Base = (LShiftU64 (MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_IGD_DEV,SA_IGD_FUN_0) + R_SA_IGD_GTTMMADR + 4), 32) + \
+ (MmioRead32 (MmPciBase(DEFAULT_PCI_BUS_NUMBER_PCH,SA_IGD_DEV,SA_IGD_FUN_0) + R_SA_IGD_GTTMMADR))) & 0x7FFF000000;
+ mNonLockableMemoryRange[NonLockableMemoryRangeGTTMMADR].End = mNonLockableMemoryRange[NonLockableMemoryRangeGTTMMADR].Base + SIZE_16MB - 1;
+
+ Msac = MmioRead8 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_IGD_DEV,SA_MC_FUN) + R_SA_IGD_MSAC_OFFSET);
+ ApertureSize = ((Msac & (BIT0 | BIT1 | BIT2 | BIT3 | BIT4)) + 1) * SIZE_128MB;
+ mNonLockableMemoryRange[NonLockableMemoryRangeGMADR].Base = (LShiftU64 (MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_IGD_DEV,SA_IGD_FUN_0) + R_SA_IGD_GMADR + 4), 32) + \
+ (MmioRead32 (MmPciBase(DEFAULT_PCI_BUS_NUMBER_PCH,SA_IGD_DEV,SA_IGD_FUN_0) + R_SA_IGD_GMADR))) & 0x7FF8000000;
+ mNonLockableMemoryRange[NonLockableMemoryRangeGMADR].End = mNonLockableMemoryRange[NonLockableMemoryRangeGMADR].Base + ApertureSize - 1;
+ }
+
+ if (MmioRead32 (MmPciBase (0,0,0) + 0x54) & BIT7) {
+ mNonLockableMemoryRange[NonLockableMemoryRangeTMBAR].Base = MmioRead64 (MmPciBase (0,4,0) + 0x10) & 0x7FFFFF8000;
+ mNonLockableMemoryRange[NonLockableMemoryRangeTMBAR].End = mNonLockableMemoryRange[NonLockableMemoryRangeTMBAR].Base + SIZE_32KB-1;
+ }
+
+ VendorIdRead = MmioRead16 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_SATA,PCI_FUNCTION_NUMBER_PCH_SATA) +0);
+ DEBUG ((DEBUG_INFO, "VendorIdRead SATA: %x\n",VendorIdRead));
+
+ if (VendorIdRead != 0xFFFF) {
+ BarRead = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_SATA,PCI_FUNCTION_NUMBER_PCH_SATA) + R_PCH_SATA_SATAGC);
+
+ if ((BarRead & BIT10) == 0 ) {
+ mNonLockableMemoryRange[NonLockableMemoryRangeABAR].Base = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_SATA,PCI_FUNCTION_NUMBER_PCH_SATA) + R_PCH_SATA_AHCI_BAR) & 0xFFFFF800;
+
+ switch (BarRead & 0x7) {
+ case V_PCH_SATA_SATAGC_ASSEL_2K:
+ AbarSize = SIZE_2KB;
+ break;
+
+ case V_PCH_SATA_SATAGC_ASSEL_16K:
+ AbarSize = SIZE_16KB;
+ break;
+
+ case V_PCH_SATA_SATAGC_ASSEL_32K:
+ AbarSize = SIZE_32KB;
+ break;
+
+ case V_PCH_SATA_SATAGC_ASSEL_64K:
+ AbarSize = SIZE_64KB;
+ break;
+
+ case V_PCH_SATA_SATAGC_ASSEL_128K:
+ AbarSize = SIZE_128KB;
+ break;
+
+ case V_PCH_SATA_SATAGC_ASSEL_512K:
+ AbarSize = SIZE_256KB;
+ break;
+
+ default:
+ AbarSize= SIZE_2KB;
+ break;
+ }
+ mNonLockableMemoryRange[NonLockableMemoryRangeABAR].End = mNonLockableMemoryRange[NonLockableMemoryRangeABAR].Base + AbarSize - 1;
+ }
+ }
+
+ mNonLockableMemoryRange[NonLockableMemoryRangeSBREG_BAR].Base = PCH_PCR_BASE_ADDRESS;
+ mNonLockableMemoryRange[NonLockableMemoryRangeSBREG_BAR].End = PCH_PCR_BASE_ADDRESS + SIZE_16MB-1;
+
+ PchPwrmBaseGet (&PwrmBase);
+ mNonLockableMemoryRange[NonLockableMemoryRangePWRMBASE].Base = PwrmBase;
+ mNonLockableMemoryRange[NonLockableMemoryRangePWRMBASE].End = PwrmBase + PCH_PWRM_MMIO_SIZE - 1;
+
+ PchSpiBase = MmioRead32 (MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI)
+ + R_PCH_SPI_BAR0) & ~B_PCH_SPI_BAR0_MASK;
+
+ mNonLockableMemoryRange[NonLockableMemoryRangeSPI_BAR0].Base = PchSpiBase;
+ mNonLockableMemoryRange[NonLockableMemoryRangeSPI_BAR0].End = PchSpiBase + SIZE_4KB-1;
+
+ DEBUG ((DEBUG_INFO, "Non lockable memory ranges:\n"));
+ DumpRange (mNonLockableMemoryRange, NonLockableMemoryRangeMax);
+ if (CheckOverlap (mNonLockableMemoryRange, NonLockableMemoryRangeMax) ||
+ CheckOverlap2 (mLockableMemoryRange, LockableMemoryRangeMax, mNonLockableMemoryRange, NonLockableMemoryRangeMax)) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_3 ,HSTI_MEMORY_MAP_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_3);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 1,
+ HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecurePCHConfiguration.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecurePCHConfiguration.c
new file mode 100644
index 0000000000..7274c5556a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecurePCHConfiguration.c
@@ -0,0 +1,299 @@
+/** @file
+ This file contains the tests for the SecuePCHConfiguration bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for SecurePCHConfiguration bit
+**/
+VOID
+CheckSecurePchConfiguration (
+ VOID
+ )
+{
+
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINT16 PmBase;
+ UINT64 Tbar;
+ UINT32 TbarL;
+ UINT32 TbarH;
+ UINT8 Srdl;
+ UINT32 GenPmConLock;
+ UINT32 PmCfg;
+ UINT32 SmiEn;
+ UINT8 GenPmCon1;
+ UINT16 Tco1Cnt;
+ UINT32 Hostc;
+ UINT16 Cmd;
+ CHAR16 *HstiErrorString;
+ UINT32 PchSpiBar0;
+ UINT32 PchPwrmBase;
+ UINT32 PcrRtc;
+ UINT16 TcoBase;
+ BOOLEAN ThermalPciMode;
+ BOOLEAN ThermalAcpiMode;
+ UINT32 ThermalPciBase;
+ BOOLEAN ThermalPciModeTbarConfigured;
+
+ ThermalPciMode = FALSE;
+ ThermalAcpiMode = FALSE;
+ ThermalPciModeTbarConfigured = FALSE;
+
+ if ((mFeatureImplemented[1] & HSTI_BYTE1_SECURE_PCH_CONFIGURATION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+
+ PchSpiBar0 = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_SPI,PCI_FUNCTION_NUMBER_PCH_SPI) + R_PCH_SPI_BAR0) & ~B_PCH_SPI_BAR0_MASK;
+
+ PchAcpiBaseGet (&PmBase);
+ PchTcoBaseGet (&TcoBase);
+
+ DEBUG ((DEBUG_INFO, " Table 3-10. PCH Security Configuration\n"));
+
+ DEBUG ((DEBUG_INFO, " 1. Thermal Throttling Locks\n"));
+
+ //
+ // Check Device VID and DID , if data is not 0xFFFFFFFF, then it's in PCI Mode
+ //
+ ThermalPciBase = (UINT32) (UINTN) MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_THERMAL,PCI_FUNCTION_NUMBER_PCH_THERMAL);
+ if (MmioRead32 (ThermalPciBase + PCI_VENDOR_ID_OFFSET) != 0xFFFFFFFF) {
+ ThermalPciMode = TRUE;
+ }
+ if (ThermalPciMode) {
+
+ TbarL = MmioRead32 (ThermalPciBase + R_PCH_THERMAL_TBAR);
+ TbarH = MmioRead32 (ThermalPciBase + R_PCH_THERMAL_TBARH);
+
+ TbarL = TbarL & B_PCH_THERMAL_TBAR_MASK;
+ Tbar = ((UINT64) TbarH << 32) | TbarL;
+
+ //
+ // Check if Tbar is initialized. If Tbar is 0 , then Tbar is not initialized , Use PCH_THERMAL_BASE_ADDRESS for Tbar
+ // and write TbarL and TbarH back to register
+ //
+ if (Tbar == 0) {
+ Tbar = (UINT64) PCH_THERMAL_BASE_ADDRESS;
+ TbarL = (UINT32) Tbar;
+ TbarH = (UINT32) ((UINT64) Tbar >> 32);
+ MmioWrite32 (ThermalPciBase + R_PCH_THERMAL_TBAR, TbarL);
+ MmioWrite32 (ThermalPciBase + R_PCH_THERMAL_TBARH, TbarH);
+ ThermalPciModeTbarConfigured = TRUE;
+ }
+ //
+ // Make sure MSE bit is enabled before trying to access Tbar MMIO
+ //
+ Cmd = MmioRead16 (ThermalPciBase + PCI_COMMAND_OFFSET);
+ MmioWrite16 (ThermalPciBase + PCI_COMMAND_OFFSET, Cmd | EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // Not in Pci Mode
+ //
+ } else {
+ Tbar = (UINT64) PCH_THERMAL_BASE_ADDRESS;
+ //
+ // This is to probe the Thermal in ACPI mode.
+ // If Thermal is in ACPI mode, the TBAR must be PCH_THERMAL_BASE_ADDRESS and the offset 0 (TEMP) must return valid temperature.
+ //
+ if (MmioRead16 ((UINT32)Tbar + 0x00) != 0xFFFF) {
+ ThermalAcpiMode = TRUE;
+ }
+ }
+
+ if (ThermalPciMode || ThermalAcpiMode) {
+ if ((MmioRead32 (Tbar + R_PCH_TBAR_TCFD) & B_PCH_TBAR_TCFD_TCD) == 0) {
+ if (((MmioRead8 (Tbar + R_PCH_TBAR_TSC) & B_PCH_TBAR_TSC_PLD) == 0) ||
+ ((MmioRead8 (Tbar + R_PCH_TBAR_TSEL) & B_PCH_TBAR_TSEL_PLD) == 0) ||
+ ((MmioRead8 (Tbar + R_PCH_TBAR_TSMIC) & B_PCH_TBAR_TSMIC_PLD) == 0) ||
+ ((MmioRead32 (Tbar + R_PCH_TBAR_TL) & B_PCH_TBAR_TL_LOCK) == 0) ||
+ ((MmioRead8 (Tbar + R_PCH_TBAR_PHLC) & BIT0) == 0)) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_1 ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_1);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+ }
+ }
+ if (ThermalPciMode) {
+ //
+ // Restore CMD register
+ //
+ MmioWrite16 ((ThermalPciBase + PCI_COMMAND_OFFSET), Cmd);
+ //
+ // If Tbar had been configured because of initialization. Restore Tbar ,TbarH and TbarL
+ //
+ if (ThermalPciModeTbarConfigured) {
+ MmioWrite32 (ThermalPciBase + R_PCH_THERMAL_TBAR, 0);
+ MmioWrite32 (ThermalPciBase + R_PCH_THERMAL_TBARH, 0);
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, " 2. Set Strap Lock\n"));
+
+ Srdl = MmioRead8 (PchSpiBar0 + R_PCH_SPI_SSML);
+ if ((Srdl & B_PCH_SPI_SSML_SSL) == 0) {
+ DEBUG ((DEBUG_INFO, "Set Strap Lock %x\n",Srdl));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_2 ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 3. ACPI Base Lock\n"));
+
+ GenPmConLock = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_PMC,PCI_FUNCTION_NUMBER_PCH_PMC) + R_PCH_PMC_GEN_PMCON_B);
+
+ if ((GenPmConLock & B_PCH_PMC_GEN_PMCON_B_ACPI_BASE_LOCK) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_2 ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_2);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 4. PM_CFG\n"));
+
+ PchPwrmBaseGet (&PchPwrmBase);
+ PmCfg = MmioRead32 (PchPwrmBase + R_PCH_PWRM_CFG);
+
+ if (((PmCfg & BIT22) == 0) ||
+ ((PmCfg & BIT27) == 0)) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_3 ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_3);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 5. SMI Enable\n"));
+
+ SmiEn = IoRead32 (PmBase + R_PCH_SMI_EN);
+ if ((SmiEn & B_PCH_SMI_EN_GBL_SMI) == 0x0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_D ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_D);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 6. SMI Lock\n"));
+
+ GenPmCon1 = MmioRead8 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_PMC,PCI_FUNCTION_NUMBER_PCH_PMC) + R_PCH_PMC_GEN_PMCON_A);
+ if ((GenPmCon1 & B_PCH_PMC_GEN_PMCON_A_SMI_LOCK) == 0x0) {
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_D ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_D);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 7. TCO SMI Lock\n"));
+
+ Tco1Cnt = IoRead16 (TcoBase + R_PCH_TCO1_CNT);
+ if ((Tco1Cnt & B_PCH_TCO_CNT_LOCK) == 0x0) {
+ DEBUG ((DEBUG_INFO, "TCO SMI Lock %x\n",(Tco1Cnt & B_PCH_TCO_CNT_LOCK)));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_E ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_E);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ DEBUG ((DEBUG_INFO, " 8. RTC Bios Interface Lock\n"));
+
+ PcrRtc = MmioRead32 (PCH_PCR_ADDRESS (PID_RTC,R_PCH_PCR_RTC_CONF));
+
+ if ((PcrRtc & BIT31) == 0x0) {
+ DEBUG ((DEBUG_INFO, "Rtc BILD %x\n",(PcrRtc & BIT31)));
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_4 ,HSTI_PCH_SECURITY_CONFIGURATION, HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_4);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+
+ DEBUG ((DEBUG_INFO, " Table 7-7. SPD Configuration and Write Protection\n"));
+
+ Hostc = MmioRead32 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,PCI_DEVICE_NUMBER_PCH_SMBUS,PCI_FUNCTION_NUMBER_PCH_SMBUS) + R_PCH_SMBUS_HOSTC);
+ if ((Hostc & B_PCH_SMBUS_HOSTC_SPDWD) == 0) {
+
+ HstiErrorString = BuildHstiErrorString (HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_4 ,HSTI_PROCESSOR_SPD_SECURITY_CONFIGURATION, HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_4);
+ Status = HstiLibAppendErrorString (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ HstiErrorString
+ );
+ ASSERT_EFI_ERROR (Status);
+ Result = FALSE;
+ FreePool (HstiErrorString);
+ }
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 1,
+ HSTI_BYTE1_SECURE_PCH_CONFIGURATION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureSystemAgentConfiguration.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureSystemAgentConfiguration.c
new file mode 100644
index 0000000000..2f498cd532
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SecureSystemAgentConfiguration.c
@@ -0,0 +1,51 @@
+/** @file
+ This file contains the tests for the SecureSystemAgentConfiguration bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for SecureSystemAgentConfiguration bit
+**/
+VOID
+CheckSecureSystemAgentConfiguration (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+ UINT32 MchBar;
+
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION) == 0) {
+ return;
+ }
+
+ Result = TRUE;
+ MchBar = (UINT32) MmioRead64 (MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH,SA_MC_DEV,SA_MC_FUN) + R_SA_MCHBAR) & B_SA_MCHBAR_MCHBAR_MASK;
+
+
+ //
+ // ALL PASS
+ //
+ if (Result) {
+ Status = HstiLibSetFeaturesVerified (
+ PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
+ NULL,
+ 0,
+ HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SignedFirmwareUpdate.c b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SignedFirmwareUpdate.c
new file mode 100644
index 0000000000..79dabc690e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Hsti/Dxe/SignedFirmwareUpdate.c
@@ -0,0 +1,30 @@
+/** @file
+ This file contains the tests for the SignedFirmwareUpdate bit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HstiSiliconDxe.h"
+
+/**
+ Run tests for SignedFirmwareUpdate bit
+**/
+VOID
+CheckSignedFirmwareUpdate (
+ VOID
+ )
+{
+ if ((mFeatureImplemented[0] & HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE) == 0) {
+ return;
+ }
+
+ return ;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/ConfigBlock.h b/Silicon/Intel/KabylakeSiliconPkg/Include/ConfigBlock.h
new file mode 100644
index 0000000000..246582e9ee
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/ConfigBlock.h
@@ -0,0 +1,59 @@
+/** @file
+ Header file for Config Block Lib implementation
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CONFIG_BLOCK_H_
+#define _CONFIG_BLOCK_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiBootMode.h>
+#include <Pi/PiHob.h>
+
+#pragma pack (push,1)
+
+///
+/// Config Block Header
+///
+typedef struct _CONFIG_BLOCK_HEADER {
+ EFI_HOB_GUID_TYPE GuidHob; ///< Offset 0-23 GUID extension HOB header
+ UINT8 Revision; ///< Offset 24 Revision of this config block
+ UINT8 Attributes; ///< Offset 25 The main revision for config block
+ UINT8 Reserved[2]; ///< Offset 26-27 Reserved for future use
+} CONFIG_BLOCK_HEADER;
+
+///
+/// Config Block
+///
+typedef struct _CONFIG_BLOCK {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Header of config block
+ //
+ // Config Block Data
+ //
+} CONFIG_BLOCK;
+
+///
+/// Config Block Table Header
+///
+typedef struct _CONFIG_BLOCK_TABLE_STRUCT {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 GUID number for main entry of config block
+ UINT8 Rsvd0[2]; ///< Offset 28-29 Reserved for future use
+ UINT16 NumberOfBlocks; ///< Offset 30-31 Number of config blocks (N)
+ UINT32 AvailableSize; ///< Offset 32-35 Current config block table size
+///
+/// Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+///
+} CONFIG_BLOCK_TABLE_HEADER;
+#pragma pack (pop)
+
+#endif // _CONFIG_BLOCK_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/HstiFeatureBit.h b/Silicon/Intel/KabylakeSiliconPkg/Include/HstiFeatureBit.h
new file mode 100644
index 0000000000..cdbe75ae18
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/HstiFeatureBit.h
@@ -0,0 +1,183 @@
+/** @file
+ This file contains various definitions for IHV HSTI implementation
+ including error string definitions
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __HSTI_FEATURE_BIT_H__
+#define __HSTI_FEATURE_BIT_H__
+
+#define HSTI_SECURITY_FEATURE_SIZE 3
+
+#define HSTI_ERROR L"Error "
+#define HSTI_PLATFORM_SECURITY_SPECIFICATION L" Platform Security Specification"
+#define HSTI_BOOTGUARD_CONFIGURATION L" - Boot Guard Configuration - "
+#define HSTI_SPI_FLASH_CONFIGURATION L" - SPI Flash Configuration - "
+#define HSTI_PCH_SECURITY_CONFIGURATION L" - PCH Security Configuration - "
+#define HSTI_BIOS_GUARD_SECURITY_CONFIGURATION L" - BIOS Guard Security Configuration - "
+#define HSTI_MEASURED_BOOT_CONFIGURATION L" - Measured Boot Configuration - "
+#define HSTI_INTEGRATED_DEVICE_DMA_PROTECTION L" - Integrated Device DMA Protection - "
+#define HSTI_CPU_SECURITY_CONFIGURATION L" - CPU Security Configuration - "
+#define HSTI_SYSTEM_AGENT_SECURITY_CONFIGURATION L" - Secure System Agent Security Configuration - "
+#define HSTI_MEMORY_MAP_SECURITY_CONFIGURATION L" - Memory Map Security Configuration - "
+#define HSTI_PROCESSOR_GRAPHICS_SECURITY_CONFIGURATION L" - Processor Graphics Security Configuration - "
+#define HSTI_PROCESSOR_SPD_SECURITY_CONFIGURATION L" - SPD Security Configuration - "
+
+
+#define HSTI_BYTE0_HARDWARE_ROOTED_BOOT_INTEGRITY BIT0
+#define HSTI_BYTE0_HARDWARE_ROOTED_BOOT_INTEGRITY_ERROR_CODE_1 L"0x00000001"
+#define HSTI_BYTE0_HARDWARE_ROOTED_BOOT_INTEGRITY_ERROR_STRING_1 L"Boot Guard configured without Verified Boot\r\n"
+#define HSTI_BYTE0_HARDWARE_ROOTED_BOOT_INTEGRITY_ERROR_CODE_2 L"0x00000002"
+#define HSTI_BYTE0_HARDWARE_ROOTED_BOOT_INTEGRITY_ERROR_STRING_2 L"Boot Guard disabled\r\n"
+
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION BIT1
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_1 L"0x00010001"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_1 L"SPI Flash not write protected\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_2 L"0x00010002"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_2 L"SPI Flash descriptor overridden\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_3 L"0x00010003"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_3 L"SPI Controller configuration unlocked\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_4 L"0x00010004"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_4 L"SPI Controller BIOS Interface unlocked\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_5 L"0x00010005"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_5 L"Top Swap enabled\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_6 L"0x00010006"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_6 L"SPI Vendor Specific Component Capabilities unlocked\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_7 L"0x00010007"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_7 L"SPI Controller GbE Interface unlocked\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_8 L"0x00010008"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_8 L"ME FW not in Normal Working State\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_9 L"0x00010009"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_9 L"Flash Descriptor Invalid\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_A L"0x0001000A"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_A L"SPI Region Access Rights Invalid\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_B L"0x0001000B"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_B L"SPI SW Sequencing OPCODEs insufficiently restrained\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_C L"0x0001000C"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_C L"Allowed SPI SW Sequencing OPCODE configuration incorrect\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_D L"0x0001000D"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_D L"Global SMI not enabled and locked\r\n"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_CODE_E L"0x0001000E"
+#define HSTI_BYTE0_BOOT_FIRMWARE_MEDIA_PROTECTION_ERROR_STRING_E L"TCO SMI not enabled and locked\r\n"
+
+#define HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE BIT2
+#define HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE_ERROR_CODE_1 L"0x00020001"
+#define HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE_ERROR_STRING_1 L"BIOS Guard unsupported\r\n"
+#define HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE_ERROR_CODE_2 L"0x00020002"
+#define HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE_ERROR_STRING_2 L"BIOS Guard configuration unlocked\r\n"
+#define HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE_ERROR_CODE_3 L"0x00020001"
+#define HSTI_BYTE0_SIGNED_FIRMWARE_UPDATE_ERROR_STRING_3 L"BIOS Guard disabled\r\n"
+
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT BIT3
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_CODE_1 L"0x00030001"
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_STRING_1 L"Chipset supports FW TPM, however no TPM enabled\r\n"
+
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_CODE_2 L"0x00030002"
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_STRING_2 L"PCR[7] is not initialized\r\n"
+
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_CODE_3 L"0x00030003"
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_STRING_3 L"Event Log is not published or invalid\r\n"
+
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_CODE_4 L"0x00030004"
+#define HSTI_BYTE0_MEASURED_BOOT_ENFORCEMENT_ERROR_STRING_4 L"Platform Auth accessible via 0x00000000\r\n"
+
+
+#define HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION BIT4
+#define HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_CODE_1 L"0x00040001"
+#define HSTI_BYTE0_INTEGRATED_DEVICE_DMA_PROTECTION_ERROR_STRING_1 L"Bus Mastering Enabled for non-boot, integrated device\r\n"
+
+#define HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION BIT5
+#define HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_CODE_1 L"0x00050001"
+#define HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_STRING_1 L"Debug MSR enabled\r\n"
+
+#define HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_CODE_2 L"0x00050002"
+#define HSTI_BYTE0_DEBUG_MODE_DISABLED_VERIFICATION_ERROR_STRING_2 L"Debug interface unlocked\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION BIT6
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_1 L"0x00060001"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_1 L" Minimum uCode patch revision not met\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_2 L"0x00060002"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_2 L" Pre-production silicon in use\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_3 L"0x00060003"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_3 L"VMX & Senter feature configuration unlocked\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_4 L"0x00060004"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_4 L" SMM Code Fetch feature configuration unlocked\r\n"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_4A L" SMM Code Fetch outside SMRAM detection feature is disabled\r\n"
+
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_5 L"0x00060005"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_5 L" AES-NI Feature configuration unlocked\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_6 L"0x00060006"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_6 L" FIT table not present\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_7 L"0x00060007"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_7 L" MicrocodeRangeRegisters improperly configured or unlocked\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_8 L"0x00060008"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_8 L" SMM COnfiguration Unlocked\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_9 L"0x00060009"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_9 L" TSEG not naturally aligned\r\n"
+
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_CODE_A L"0x0006000A"
+#define HSTI_BYTE0_SECURE_CPU_CONFIGURATION_ERROR_STRING_A L" Improper SMRR configuration\r\n"
+
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION BIT7
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_CODE_1 L"0x00070001"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_STRING_1 L"Intel TXT configuration unlocked\r\n"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_CODE_2 L"0x00070002"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_STRING_2 L"Memory Controller configuration unlocked\r\n"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_CODE_3 L"0x00070003"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_STRING_3 L"System Agent configuration unlocked\r\n"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_CODE_4 L"0x00070004"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_STRING_4 L"Graphics memory configuration unlocked\r\n"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_CODE_5 L"0x00070005"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_STRING_5 L"VT-d configuration unlocked\r\n"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_CODE_6 L"0x00070006"
+#define HSTI_BYTE0_SECURE_SYSTEM_AGENT_CONFIGURATION_ERROR_STRING_6 L"Power Plane 0 Current Config unlocked\r\n"
+
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION BIT0
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_1 L"0x00080001"
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_1 L" Memory BAR configuration unlocked\r\n"
+
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_2 L"0x00080002"
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_2 L" Fixed MMIO regions overlap\r\n"
+
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_3 L"0x00080003"
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_3 L" Non lockable MMIO ranges overlap other critical regions\r\n"
+
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_CODE_4 L"0x00080004"
+#define HSTI_BYTE1_SECURE_MEMORY_MAP_CONFIGURATION_ERROR_STRING_4 L" SPD not write protected\r\n"
+
+#define HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION BIT1
+#define HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_1 L"0x00090001"
+#define HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_1 L" Graphics configuration unlocked\r\n"
+
+#define HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_2 L"0x00090002"
+#define HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_2 L"Invalid Graphics Memory Alignment\r\n"
+
+#define HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_CODE_3 L"0x00090003"
+#define HSTI_BYTE1_SECURE_INTEGRATED_GRAPHICS_CONFIGURATION_ERROR_STRING_3 L" Reserved Check failed\r\n"
+
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION BIT2
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_1 L"0x000A0001"
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_1 L" Thermal Configuration unlocked\r\n"
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_2 L"0x000A0002"
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_2 L"BAR's unlocked\r\n"
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_CODE_3 L"0x000A0003"
+#define HSTI_BYTE1_SECURE_PCH_CONFIGURATION_ERROR_STRING_3 L" Reserved Check failure\r\n"
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Library/AslUpdateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/AslUpdateLib.h
new file mode 100644
index 0000000000..dc76e33557
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/AslUpdateLib.h
@@ -0,0 +1,146 @@
+/** @file
+ ASL dynamic update library definitions.
+ This library provides dymanic update to various ASL structures.
+ There may be different libraries for different environments (PEI, BS, RT, SMM).
+ Make sure you meet the requirements for the library (protocol dependencies, use
+ restrictions, etc).
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ASL_UPDATE_LIB_H_
+#define _ASL_UPDATE_LIB_H_
+
+//
+// Include files
+//
+#include <IndustryStandard/Acpi.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+
+//
+// AML parsing definitions
+//
+#define AML_RESRC_TEMP_END_TAG 0x0079
+
+//
+// ASL PSS package structure layout
+//
+#pragma pack (1)
+typedef struct {
+ UINT8 NameOp; // 12h ;First opcode is a NameOp.
+ UINT8 PackageLead; // 20h ;First opcode is a NameOp.
+ UINT8 NumEntries; // 06h ;First opcode is a NameOp.
+ UINT8 DwordPrefix1; // 0Ch
+ UINT32 CoreFrequency; // 00h
+ UINT8 DwordPrefix2; // 0Ch
+ UINT32 Power; // 00h
+ UINT8 DwordPrefix3; // 0Ch
+ UINT32 TransLatency; // 00h
+ UINT8 DwordPrefix4; // 0Ch
+ UINT32 BmLatency; // 00h
+ UINT8 DwordPrefix5; // 0Ch
+ UINT32 Control; // 00h
+ UINT8 DwordPrefix6; // 0Ch
+ UINT32 Status; // 00h
+} PSS_PACKAGE_LAYOUT;
+#pragma pack()
+
+/**
+ Initialize the ASL update library state.
+ This must be called prior to invoking other library functions.
+
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+InitializeAslUpdateLib (
+ VOID
+ );
+
+/**
+ This procedure will update immediate value assigned to a Name
+
+ @param[in] AslSignature The signature of Operation Region that we want to update.
+ @param[in] Buffer source of data to be written over original aml
+ @param[in] Length length of data to be overwritten
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+UpdateNameAslCode(
+ IN UINT32 AslSignature,
+ IN VOID *Buffer,
+ IN UINTN Length
+ );
+
+/**
+ This function uses the ACPI support protocol to locate an ACPI table using the .
+ It is really only useful for finding tables that only have a single instance,
+ e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc.
+ Matches are determined by finding the table with ACPI table that has
+ a matching signature and version.
+
+ @param[in] Signature Pointer to an ASCII string containing the Signature to match
+ @param[in, out] Table Updated with a pointer to the table
+ @param[in, out] Handle AcpiSupport protocol table handle for the table found
+ @param[in, out] Version On input, the version of the table desired,
+ on output, the versions the table belongs to
+ @see AcpiSupport protocol for details
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableBySignature (
+ IN UINT32 Signature,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ );
+
+/**
+ This function uses the ACPI support protocol to locate an ACPI SSDT table.
+ The table is located by searching for a matching OEM Table ID field.
+ Partial match searches are supported via the TableIdSize parameter.
+
+ @param[in] TableId Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in] TableIdSize Length of the TableId to match. Table ID are 8 bytes long, this function
+ will consider it a match if the first TableIdSize bytes match
+ @param[in, out] Table Updated with a pointer to the table
+ @param[in, out] Handle AcpiSupport protocol table handle for the table found
+ @param[in, out] Version See AcpiSupport protocol, GetAcpiTable function for use
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableByOemTableId (
+ IN UINT8 *TableId,
+ IN UINT8 TableIdSize,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ );
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param[in] Buffer Pointer to buffer to checksum
+ @param[in] Size Number of bytes to checksum
+ @param[in] ChecksumOffset Offset to place the checksum result in
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+AcpiChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Library/ConfigBlockLib.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/ConfigBlockLib.h
new file mode 100644
index 0000000000..cc437b93bf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/ConfigBlockLib.h
@@ -0,0 +1,70 @@
+/** @file
+ Header file for Config Block Lib implementation
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CONFIG_BLOCK_LIB_H_
+#define _CONFIG_BLOCK_LIB_H_
+
+/**
+ Create config block table
+
+ @param[in] TotalSize - Max size to be allocated for the Config Block Table
+ @param[out] ConfigBlockTableAddress - On return, points to a pointer to the beginning of Config Block Table Address
+
+ @retval EFI_INVALID_PARAMETER - Invalid Parameter
+ @retval EFI_OUT_OF_RESOURCES - Out of resources
+ @retval EFI_SUCCESS - Successfully created Config Block Table at ConfigBlockTableAddress
+**/
+EFI_STATUS
+EFIAPI
+CreateConfigBlockTable (
+ IN UINT16 TotalSize,
+ OUT VOID **ConfigBlockTableAddress
+ );
+
+/**
+ Add config block into config block table structure
+
+ @param[in] ConfigBlockTableAddress - A pointer to the beginning of Config Block Table Address
+ @param[out] ConfigBlockAddress - On return, points to a pointer to the beginning of Config Block Address
+
+ @retval EFI_OUT_OF_RESOURCES - Config Block Table is full and cannot add new Config Block or
+ Config Block Offset Table is full and cannot add new Config Block.
+ @retval EFI_SUCCESS - Successfully added Config Block
+**/
+EFI_STATUS
+EFIAPI
+AddConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ OUT VOID **ConfigBlockAddress
+ );
+
+/**
+ Retrieve a specific Config Block data by GUID
+
+ @param[in] ConfigBlockTableAddress - A pointer to the beginning of Config Block Table Address
+ @param[in] ConfigBlockGuid - A pointer to the GUID uses to search specific Config Block
+ @param[out] ConfigBlockAddress - On return, points to a pointer to the beginning of Config Block Address
+
+ @retval EFI_NOT_FOUND - Could not find the Config Block
+ @retval EFI_SUCCESS - Config Block found and return
+**/
+EFI_STATUS
+EFIAPI
+GetConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ IN EFI_GUID *ConfigBlockGuid,
+ OUT VOID **ConfigBlockAddress
+ );
+
+#endif // _CONFIG_BLOCK_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Library/MmPciLib.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/MmPciLib.h
new file mode 100644
index 0000000000..b4f8b41e1b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/MmPciLib.h
@@ -0,0 +1,34 @@
+/** @file
+ Get Pci Express address library implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _MM_PCI_LIB_H_
+#define _MM_PCI_LIB_H_
+
+/**
+ This procedure will get PCIE address
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+
+ @retval PCIE address
+**/
+UINTN
+MmPciBase (
+ IN UINT32 Bus,
+ IN UINT32 Device,
+ IN UINT32 Function
+);
+
+#endif // _PEI_DXE_SMM_MM_PCI_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Library/PeiSiPolicyUpdateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/PeiSiPolicyUpdateLib.h
new file mode 100644
index 0000000000..184b04f5de
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/PeiSiPolicyUpdateLib.h
@@ -0,0 +1,143 @@
+/** @file
+ Header file for PEI SiPolicyUpdate Library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_SI_POLICY_UPDATE_LIB_H_
+#define _PEI_SI_POLICY_UPDATE_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+
+/**
+ This function performs Silicon PEI Policy initialization.
+
+ @param[in, out] SiPolicy The Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+EFIAPI
+UpdatePeiSiPolicy (
+ IN OUT SI_POLICY_PPI *SiPolicy
+ );
+
+/**
+ This function performs CPU PEI Policy initialization in Post-memory.
+
+ @param[in, out] SiPolicyPpi The SI Policy PPI instance
+
+ @retval EFI_SUCCESS The PPI is installed and initialized.
+ @retval EFI ERRORS The PPI is not successfully installed.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+UpdatePeiCpuPolicy (
+ IN OUT SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ This function performs SI PEI Policy initialization.
+
+ @param[in, out] SiPolicyPpi The SA Policy PPI instance
+
+ @retval EFI_SUCCESS The PPI is installed and initialized.
+**/
+EFI_STATUS
+EFIAPI
+UpdatePeiSaPolicy (
+ IN OUT SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+This function performs SA PEI Policy initialization for PreMem.
+
+@param[in, out] SiPreMemPolicyPpi The SI PreMem Policy PPI instance
+
+@retval EFI_SUCCESS Update complete.
+**/
+EFI_STATUS
+EFIAPI
+UpdatePeiSaPolicyPreMem (
+IN OUT SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+);
+
+/**
+ This function performs PCH PEI Policy initialization.
+
+ @param[in, out] SiPolicy The SI Policy PPI instance
+
+ @retval EFI_SUCCESS The PPI is installed and initialized.
+ @retval EFI ERRORS The PPI is not successfully installed.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+UpdatePeiPchPolicy (
+ IN OUT SI_POLICY_PPI *SiPolicy
+ );
+
+/**
+ This function performs PCH PEI Policy initialization.
+
+ @param[in, out] SiPreMemPolicy The SI PreMem Policy PPI instance
+
+ @retval EFI_SUCCESS The PPI is installed and initialized.
+ @retval EFI ERRORS The PPI is not successfully installed.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+UpdatePeiPchPolicyPreMem (
+ IN OUT SI_PREMEM_POLICY_PPI *SiPreMemPolicy
+ );
+
+/**
+ Update the ME Policy Library
+
+ @param[in, out] SiPolicy The SI Policy PPI instance
+
+ @retval EFI_SUCCESS Update complete.
+**/
+EFI_STATUS
+UpdatePeiMePolicy (
+ IN OUT SI_POLICY_PPI *SiPolicy
+ );
+
+/**
+ Update the ME Policy Library
+
+ @param[in, out] SiPreMemPolicy The SI PreMem Policy PPI instance
+
+ @retval EFI_SUCCESS Update complete.
+**/
+EFI_STATUS
+UpdatePeiMePolicyPreMem (
+ IN OUT SI_PREMEM_POLICY_PPI *SiPreMemPolicy
+ );
+
+/**
+ Install the Active Management Policy Ppi Library
+
+ @param[in, out] SiPolicy The SI Policy PPI instance
+
+ @retval EFI_SUCCESS Initialization complete.
+ @retval EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+UpdatePeiAmtPolicy (
+ IN OUT SI_POLICY_PPI *SiPolicy
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiConfigBlockLib.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiConfigBlockLib.h
new file mode 100644
index 0000000000..56527478b4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiConfigBlockLib.h
@@ -0,0 +1,64 @@
+/** @file
+ Prototype of the SiConfigBlockLib library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_CONFIG_BLOCK_LIB_H_
+#define _SI_CONFIG_BLOCK_LIB_H_
+
+
+typedef
+VOID
+(*LOAD_DEFAULT_FUNCTION) (
+ IN VOID *ConfigBlockPointer
+ );
+
+typedef struct {
+ EFI_GUID *Guid;
+ UINT16 Size;
+ UINT8 Revision;
+ LOAD_DEFAULT_FUNCTION LoadDefault;
+} COMPONENT_BLOCK_ENTRY;
+
+/**
+ GetComponentConfigBlockTotalSize get config block table total size.
+
+ @param[in] ComponentBlocks Component blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval Size of config block table
+**/
+UINT16
+EFIAPI
+GetComponentConfigBlockTotalSize (
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ );
+
+/**
+ AddComponentConfigBlocks add all config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add config blocks
+ @param[in] ComponentBlocks Config blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+AddComponentConfigBlocks (
+ IN VOID *ConfigBlockTableAddress,
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ );
+#endif // _SI_CONFIG_BLOCK_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiPolicyLib.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiPolicyLib.h
new file mode 100644
index 0000000000..98d3ad25e0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiPolicyLib.h
@@ -0,0 +1,114 @@
+/** @file
+ Prototype of the SiPolicyLib library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_POLICY_LIB_H_
+#define _SI_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+
+/**
+ Print whole SI_PREMEM_POLICY_PPI and serial out.
+
+ @param[in] SiPreMemPolicyPpi The RC PREMEM Policy PPI instance
+**/
+VOID
+EFIAPI
+SiPreMemPrintPolicyPpi (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+ );
+
+/**
+ Print whole SI_POLICY_PPI and serial out.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+SiPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ SiCreatePreMemConfigBlocks creates the config blocksg of Silicon Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SiPreMemPolicyPpi The pointer to get Silicon PREMEM Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiCreatePreMemConfigBlocks (
+ OUT SI_PREMEM_POLICY_PPI **SiPreMemPolicyPpi
+ );
+
+/**
+ SiCreateConfigBlocks creates the config blocksg of Silicon Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SiPolicyPpi The pointer to get Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiCreateConfigBlocks (
+ OUT SI_POLICY_PPI **SiPolicyPpi
+ );
+
+/**
+ SiPreMemInstallPolicyPpi installs SiPreMemPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] SiPreMemPolicyPpi The pointer to Silicon PREMEM Policy PPI instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiPreMemInstallPolicyPpi (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+ );
+
+/**
+ SiInstallPolicyPpi installs SiPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] SiPolicyPpi The pointer to Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiInstallPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ Print out all silicon policy information.
+
+ @param[in] SiPolicyPpi The pointer to Silicon Policy PPI instance
+
+**/
+VOID
+DumpSiPolicy (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+#endif // _SI_PREMEM_POLICY_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiliconInitLib.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiliconInitLib.h
new file mode 100644
index 0000000000..d10e7cf0b8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Library/SiliconInitLib.h
@@ -0,0 +1,34 @@
+/** @file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SILICON_INIT_LIB_H_
+#define _SILICON_INIT_LIB_H_
+
+///@todo it should be moved to Si Pkg.
+
+VOID
+EarlySiliconInit (
+ VOID
+ );
+
+VOID
+SiliconInit (
+ VOID
+ );
+
+VOID
+LateSiliconInit (
+ VOID
+ );
+
+#endif \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/PcieRegs.h b/Silicon/Intel/KabylakeSiliconPkg/Include/PcieRegs.h
new file mode 100644
index 0000000000..3a3b22fd83
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/PcieRegs.h
@@ -0,0 +1,309 @@
+/** @file
+ Register names for PCIE standard register
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCIE_REGS_H_
+#define _PCIE_REGS_H_
+
+#include <IndustryStandard/Pci30.h>
+
+//
+// PCI type 0 Header
+//
+#define R_PCI_PI_OFFSET 0x09
+#define R_PCI_SCC_OFFSET 0x0A
+#define R_PCI_BCC_OFFSET 0x0B
+
+//
+// PCI type 1 Header
+//
+#define R_PCI_BRIDGE_BNUM 0x18 ///< Bus Number Register
+#define B_PCI_BRIDGE_BNUM_SBBN 0x00FF0000 ///< Subordinate Bus Number
+#define B_PCI_BRIDGE_BNUM_SCBN 0x0000FF00 ///< Secondary Bus Number
+#define B_PCI_BRIDGE_BNUM_PBN 0x000000FF ///< Primary Bus Number
+#define B_PCI_BRIDGE_BNUM_SBBN_SCBN (B_PCI_BRIDGE_BNUM_SBBN | B_PCI_BRIDGE_BNUM_SCBN)
+
+#define R_PCI_BRIDGE_IOBL 0x1C ///< I/O Base and Limit Register
+
+#define R_PCI_BRIDGE_MBL 0x20 ///< Memory Base and Limit Register
+#define B_PCI_BRIDGE_MBL_ML 0xFFF00000 ///< Memory Limit
+#define B_PCI_BRIDGE_MBL_MB 0x0000FFF0 ///< Memory Base
+
+#define R_PCI_BRIDGE_PMBL 0x24 ///< Prefetchable Memory Base and Limit Register
+#define B_PCI_BRIDGE_PMBL_PML 0xFFF00000 ///< Prefetchable Memory Limit
+#define B_PCI_BRIDGE_PMBL_I64L 0x000F0000 ///< 64-bit Indicator
+#define B_PCI_BRIDGE_PMBL_PMB 0x0000FFF0 ///< Prefetchable Memory Base
+#define B_PCI_BRIDGE_PMBL_I64B 0x0000000F ///< 64-bit Indicator
+
+#define R_PCI_BRIDGE_PMBU32 0x28 ///< Prefetchable Memory Base Upper 32-Bit Register
+#define B_PCI_BRIDGE_PMBU32 0xFFFFFFFF
+
+#define R_PCI_BRIDGE_PMLU32 0x2C ///< Prefetchable Memory Limit Upper 32-Bit Register
+#define B_PCI_BRIDGE_PMLU32 0xFFFFFFFF
+
+//
+// PCIE capabilities register
+//
+#define R_PCIE_CAP_ID_OFFSET 0x00 ///< Capability ID
+#define R_PCIE_CAP_NEXT_PRT_OFFSET 0x01 ///< Next Capability Capability ID Pointer
+
+//
+// PCI Express Capability List Register (CAPID:10h)
+//
+#define R_PCIE_XCAP_OFFSET 0x02 ///< PCI Express Capabilities Register (Offset 02h)
+#define S_PCIE_XCAP 2
+#define B_PCIE_XCAP_SI BIT8 ///< Slot Implemented
+#define B_PCIE_XCAP_DT (BIT7 | BIT6 | BIT5 | BIT4) ///< Device/Port Type
+#define N_PCIE_XCAP_DT 4
+
+#define R_PCIE_DCAP_OFFSET 0x04 ///< Device Capabilities Register (Offset 04h)
+#define S_PCIE_DCAP 4
+#define B_PCIE_DCAP_E1AL (BIT11 | BIT10 | BIT9) ///< Endpoint L1 Acceptable Latency
+#define N_PCIE_DCAP_E1AL 9
+#define B_PCIE_DCAP_E0AL (BIT8 | BIT7 | BIT6) ///< Endpoint L0s Acceptable Latency
+#define N_PCIE_DCAP_E0AL 6
+#define B_PCIE_DCAP_MPS (BIT2 | BIT1 | BIT0) ///< Max_Payload_Size Supported
+
+#define R_PCIE_DCTL_OFFSET 0x08 ///< Device Control Register (Offset 08h)
+#define B_PCIE_DCTL_MPS (BIT7 | BIT6 | BIT5) ///< Max_Payload_Size
+#define N_PCIE_DCTL_MPS 5
+#define B_PCIE_DCTL_URE BIT3 ///< Unsupported Request Reporting Enable
+#define B_PCIE_DCTL_FEE BIT2 ///< Fatal Error Reporting Enable
+#define B_PCIE_DCTL_NFE BIT1 ///< Non-Fatal Error Reporting Enable
+#define B_PCIE_DCTL_CEE BIT0 ///< Correctable Error Reporting Enable
+
+#define R_PCIE_DSTS_OFFSET 0x0A ///< Device Status Register (Offset 0Ah)
+#define B_PCIE_DSTS_TDP BIT5 ///< Transactions Pending
+#define B_PCIE_DSTS_APD BIT4 ///< AUX Power Detected
+#define B_PCIE_DSTS_URD BIT3 ///< Unsupported Request Detected
+#define B_PCIE_DSTS_FED BIT2 ///< Fatal Error Detected
+#define B_PCIE_DSTS_NFED BIT1 ///< Non-Fatal Error Detected
+#define B_PCIE_DSTS_CED BIT0 ///< Correctable Error Detected
+
+#define R_PCIE_LCAP_OFFSET 0x0C ///< Link Capabilities Register (Offset 0Ch)
+#define B_PCIE_LCAP_ASPMOC BIT22 ///< ASPM Optionality Compliance
+#define B_PCIE_LCAP_CPM BIT18 ///< Clock Power Management
+#define B_PCIE_LCAP_EL1 (BIT17 | BIT16 | BIT15) ///< L1 Exit Latency
+#define N_PCIE_LCAP_EL1 15
+#define B_PCIE_LCAP_EL0 (BIT14 | BIT13 | BIT12) ///< L0s Exit Latency
+#define N_PCIE_LCAP_EL0 12
+#define B_PCIE_LCAP_APMS (BIT11 | BIT10) ///< Active State Power Management (ASPM) Support
+#define B_PCIE_LCAP_APMS_L0S BIT10
+#define B_PCIE_LCAP_APMS_L1 BIT11
+#define N_PCIE_LCAP_APMS 10
+#define B_PCIE_LCAP_MLW 0x000003F0 ///< Maximum Link Width
+#define N_PCIE_LCAP_MLW 4
+#define B_PCIE_LCAP_MLS (BIT3 | BIT2 | BIT1 | BIT0) ///< Max Link Speed
+#define V_PCIE_LCAP_MLS_GEN3 3
+
+#define R_PCIE_LCTL_OFFSET 0x10 ///< Link Control Register (Offset 10h)
+#define B_PCIE_LCTL_ECPM BIT8 ///< Enable Clock Power Management
+#define B_PCIE_LCTL_ES BIT7 ///< Extended Synch
+#define B_PCIE_LCTL_CCC BIT6 ///< Common Clock Configuration
+#define B_PCIE_LCTL_RL BIT5 ///< Retrain Link
+#define B_PCIE_LCTL_LD BIT4 ///< Link Disable
+#define B_PCIE_LCTL_ASPM (BIT1 | BIT0) ///< Active State Power Management (ASPM) Control
+#define V_PCIE_LCTL_ASPM_L0S 1
+#define V_PCIE_LCTL_ASPM_L1 2
+#define V_PCIE_LCTL_ASPM_L0S_L1 3
+
+#define R_PCIE_LSTS_OFFSET 0x12 ///< Link Status Register (Offset 12h)
+#define B_PCIE_LSTS_LA BIT13 ///< Data Link Layer Link Active
+#define B_PCIE_LSTS_SCC BIT12 ///< Slot Clock Configuration
+#define B_PCIE_LSTS_LT BIT11 ///< Link Training
+#define B_PCIE_LSTS_NLW 0x03F0 ///< Negotiated Link Width
+#define N_PCIE_LSTS_NLW 4
+#define V_PCIE_LSTS_NLW_1 0x0010
+#define V_PCIE_LSTS_NLW_2 0x0020
+#define V_PCIE_LSTS_NLW_4 0x0040
+#define B_PCIE_LSTS_CLS 0x000F ///< Current Link Speed
+#define V_PCIE_LSTS_CLS_GEN1 1
+#define V_PCIE_LSTS_CLS_GEN2 2
+#define V_PCIE_LSTS_CLS_GEN3 3
+
+#define R_PCIE_SLCAP_OFFSET 0x14 ///< Slot Capabilities Register (Offset 14h)
+#define S_PCIE_SLCAP 4
+#define B_PCIE_SLCAP_PSN 0xFFF80000 ///< Physical Slot Number
+#define B_PCIE_SLCAP_SLS 0x00018000 ///< Slot Power Limit Scale
+#define B_PCIE_SLCAP_SLV 0x00007F80 ///< Slot Power Limit Value
+#define B_PCIE_SLCAP_HPC BIT6 ///< Hot-Plug Capable
+#define B_PCIE_SLCAP_HPS BIT5 ///< Hot-Plug Surprise
+
+#define R_PCIE_SLCTL_OFFSET 0x18 ///< Slot Control Register (Offset 18h)
+#define S_PCIE_SLCTL 2
+#define B_PCIE_SLCTL_HPE BIT5 ///< Hot Plug Interrupt Enable
+#define B_PCIE_SLCTL_PDE BIT3 ///< Presence Detect Changed Enable
+
+#define R_PCIE_SLSTS_OFFSET 0x1A ///< Slot Status Register (Offset 1Ah)
+#define S_PCIE_SLSTS 2
+#define B_PCIE_SLSTS_PDS BIT6 ///< Presence Detect State
+#define B_PCIE_SLSTS_PDC BIT3 ///< Presence Detect Changed
+
+#define R_PCIE_RCTL_OFFSET 0x1C ///< Root Control Register (Offset 1Ch)
+#define S_PCIE_RCTL 2
+#define B_PCIE_RCTL_PIE BIT3 ///< PME Interrupt Enable
+#define B_PCIE_RCTL_SFE BIT2 ///< System Error on Fatal Error Enable
+#define B_PCIE_RCTL_SNE BIT1 ///< System Error on Non-Fatal Error Enable
+#define B_PCIE_RCTL_SCE BIT0 ///< System Error on Correctable Error Enable
+
+#define R_PCIE_RSTS_OFFSET 0x20 ///< Root Status Register (Offset 20h)
+#define S_PCIE_RSTS 4
+
+#define R_PCIE_DCAP2_OFFSET 0x24 ///< Device Capabilities 2 Register (Offset 24h)
+#define B_PCIE_DCAP2_OBFFS (BIT19 | BIT18) ///< OBFF Supported
+#define B_PCIE_DCAP2_LTRMS BIT11 ///< LTR Mechanism Supported
+
+#define R_PCIE_DCTL2_OFFSET 0x28 ///< Device Control 2 Register (Offset 28h)
+#define B_PCIE_DCTL2_OBFFEN (BIT14 | BIT13) ///< OBFF Enable
+#define N_PCIE_DCTL2_OBFFEN 13
+#define V_PCIE_DCTL2_OBFFEN_DIS 0 ///< Disabled
+#define V_PCIE_DCTL2_OBFFEN_WAKE 3 ///< Enabled using WAKE# signaling
+#define B_PCIE_DCTL2_LTREN BIT10 ///< LTR Mechanism Enable
+#define B_PCIE_DCTL2_CTD BIT4 ///< Completion Timeout Disable
+#define B_PCIE_DCTL2_CTV (BIT3 | BIT2 | BIT1 | BIT0) ///< Completion Timeout Value
+#define V_PCIE_DCTL2_CTV_DEFAULT 0x0
+#define V_PCIE_DCTL2_CTV_40MS_50MS 0x5
+#define V_PCIE_DCTL2_CTV_160MS_170MS 0x6
+#define V_PCIE_DCTL2_CTV_400MS_500MS 0x9
+#define V_PCIE_DCTL2_CTV_1P6S_1P7S 0xA
+
+#define R_PCIE_LCTL2_OFFSET 0x30 ///< Link Control 2 Register (Offset 30h)
+#define B_PCIE_LCTL2_SD BIT6 ///< Selectable de-emphasis (0 = -6dB, 1 = -3.5dB)
+#define B_PCIE_LCTL2_TLS (BIT3 | BIT2 | BIT1 | BIT0) ///< Target Link Speed
+#define V_PCIE_LCTL2_TLS_GEN1 1
+#define V_PCIE_LCTL2_TLS_GEN2 2
+#define V_PCIE_LCTL2_TLS_GEN3 3
+
+#define R_PCIE_LSTS2_OFFSET 0x32 ///< Link Status 2 Register (Offset 32h)
+#define B_PCIE_LSTS2_LER BIT5 ///< Link Equalization Request
+#define B_PCIE_LSTS2_EQP3S BIT4 ///< Equalization Phase 3 Successful
+#define B_PCIE_LSTS2_EQP2S BIT3 ///< Equalization Phase 2 Successful
+#define B_PCIE_LSTS2_EQP1S BIT2 ///< Equalization Phase 1 Successful
+#define B_PCIE_LSTS2_EC BIT1 ///< Equalization Complete
+#define B_PCIE_LSTS2_CDL BIT0 ///< Current De-emphasis Level
+
+//
+// PCI Power Management Capability (CAPID:01h)
+//
+#define R_PCIE_PMC_OFFSET 0x02 ///< Power Management Capabilities Register
+#define S_PCIE_PMC 2
+#define B_PCIE_PMC_PMES (BIT15 | BIT14 | BIT13 | BIT12 | BIT11) ///< PME Support
+#define B_PCIE_PMC_PMEC BIT3 ///< PME Clock
+
+#define R_PCIE_PMCS_OFFST 0x04 ///< Power Management Status/Control Register
+#define S_PCIE_PMCS 4
+#define B_PCIE_PMCS_BPCE BIT23 ///< Bus Power/Clock Control Enable
+#define B_PCIE_PMCS_B23S BIT22 ///< B2/B3 Support
+#define B_PCIE_PMCS_PMES BIT15 ///< PME_Status
+#define B_PCIE_PMCS_PMEE BIT8 ///< PME Enable
+#define B_PCIE_PMCS_NSR BIT3 ///< No Soft Reset
+#define B_PCIE_PMCS_PS (BIT1 | BIT0) ///< Power State
+#define V_PCIE_PMCS_PS_D0 0
+#define V_PCIE_PMCS_PS_D3H 3
+
+//
+// PCIE Extension Capability Register
+//
+#define B_PCIE_EXCAP_NCO 0xFFF00000 ///< Next Capability Offset
+#define N_PCIE_EXCAP_NCO 20
+#define V_PCIE_EXCAP_NCO_LISTEND 0
+#define B_PCIE_EXCAP_CV 0x000F0000 ///< Capability Version
+#define N_PCIE_EXCAP_CV 16
+#define B_PCIE_EXCAP_CID 0x0000FFFF ///< Capability ID
+
+//
+// Advanced Error Reporting Capability (CAPID:0001h)
+//
+#define V_PCIE_EX_AEC_CID 0x0001 ///< Capability ID
+#define R_PCIE_EX_UEM_OFFSET 0x08 ///< Uncorrectable Error Mask Register
+#define B_PCIE_EX_UEM_CT BIT14 ///< Completion Timeout Mask
+#define B_PCIE_EX_UEM_UC BIT16 ///< Unexpected Completion
+
+//
+// ACS Extended Capability (CAPID:000Dh)
+//
+#define V_PCIE_EX_ACS_CID 0x000D ///< Capability ID
+#define R_PCIE_EX_ACSCAPR_OFFSET 0x04 ///< ACS Capability Register
+//#define R_PCIE_EX_ACSCTLR_OFFSET 0x08 ///< ACS Control Register (NOTE: register size in PCIE spce is not match the PCH register size)
+
+//
+// Secondary PCI Express Extended Capability Header (CAPID:0019h)
+//
+#define V_PCIE_EX_SPE_CID 0x0019 ///< Capability ID
+#define R_PCIE_EX_LCTL3_OFFSET 0x04 ///< Link Control 3 Register
+#define B_PCIE_EX_LCTL3_PE BIT0 ///< Perform Equalization
+#define R_PCIE_EX_LES_OFFSET 0x08 ///< Lane Error Status
+#define R_PCIE_EX_L01EC_OFFSET 0x0C ///< Lane 0 and Lan 1 Equalization Control Register (Offset 0Ch)
+#define B_PCIE_EX_L01EC_UPL1TP 0x0F000000 ///< Upstream Port Lane 1 Transmitter Preset
+#define N_PCIE_EX_L01EC_UPL1TP 24
+#define B_PCIE_EX_L01EC_DPL1TP 0x000F0000 ///< Downstream Port Lane 1 Transmitter Preset
+#define N_PCIE_EX_L01EC_DPL1TP 16
+#define B_PCIE_EX_L01EC_UPL0TP 0x00000F00 ///< Upstream Port Transmitter Preset
+#define N_PCIE_EX_L01EC_UPL0TP 8
+#define B_PCIE_EX_L01EC_DPL0TP 0x0000000F ///< Downstream Port Transmitter Preset
+#define N_PCIE_EX_L01EC_DPL0TP 0
+
+#define R_PCIE_EX_L23EC_OFFSET 0x10 ///< Lane 2 and Lane 3 Equalization Control Register (Offset 10h)
+#define B_PCIE_EX_L23EC_UPL3TP 0x0F000000 ///< Upstream Port Lane 3 Transmitter Preset
+#define N_PCIE_EX_L23EC_UPL3TP 24
+#define B_PCIE_EX_L23EC_DPL3TP 0x000F0000 ///< Downstream Port Lane 3 Transmitter Preset
+#define N_PCIE_EX_L23EC_DPL3TP 16
+#define B_PCIE_EX_L23EC_UPL2TP 0x00000F00 ///< Upstream Port Lane 2 Transmitter Preset
+#define N_PCIE_EX_L23EC_UPL2TP 8
+#define B_PCIE_EX_L23EC_DPL2TP 0x0000000F ///< Downstream Port Lane 2 Transmitter Preset
+#define N_PCIE_EX_L23EC_DPL2TP 0
+
+
+//
+// L1 Sub-States Extended Capability Register (CAPID:001Eh)
+//
+#define V_PCIE_EX_L1S_CID 0x001E ///< Capability ID
+#define R_PCIE_EX_L1SCAP_OFFSET 0x04 ///< L1 Sub-States Capabilities
+#define B_PCIE_EX_L1SCAP_PTV 0x00F80000 //< Port Tpower_on value
+#define N_PCIE_EX_L1SCAP_PTV 19
+#define B_PCIE_EX_L1SCAP_PTPOS 0x00030000 //< Port Tpower_on scale
+#define N_PCIE_EX_L1SCAP_PTPOS 16
+#define V_PCIE_EX_L1SCAP_PTPOS_2us 0
+#define V_PCIE_EX_L1SCAP_PTPOS_10us 1
+#define V_PCIE_EX_L1SCAP_PTPOS_100us 2
+#define B_PCIE_EX_L1SCAP_L1PSS BIT4 ///< L1 PM substates supported
+#define B_PCIE_EX_L1SCAP_AL1SS BIT3 ///< ASPM L1.1 supported
+#define B_PCIE_EX_L1SCAP_AL12S BIT2 ///< ASPM L1.2 supported
+#define B_PCIE_EX_L1SCAP_PPL11S BIT1 ///< PCI-PM L1.1 supported
+#define B_PCIE_EX_L1SCAP_PPL12S BIT0 ///< PCI-PM L1.2 supported
+#define R_PCIE_EX_L1SCTL1_OFFSET 0x08 ///< L1 Sub-States Control 1
+#define R_PCIE_EX_L1SCTL2_OFFSET 0x0C ///< L1 Sub-States Control 2
+#define N_PCIE_EX_L1SCTL2_POWT 3
+
+//
+// Base Address Offset
+//
+#define R_BASE_ADDRESS_OFFSET_0 0x0010 ///< Base Address Register 0
+#define R_BASE_ADDRESS_OFFSET_1 0x0014 ///< Base Address Register 1
+#define R_BASE_ADDRESS_OFFSET_2 0x0018 ///< Base Address Register 2
+#define R_BASE_ADDRESS_OFFSET_3 0x001C ///< Base Address Register 3
+#define R_BASE_ADDRESS_OFFSET_4 0x0020 ///< Base Address Register 4
+#define R_BASE_ADDRESS_OFFSET_5 0x0024 ///< Base Address Register 5
+#define B_PCI_BAR_MEMORY_TYPE_MASK (BIT1 | BIT2)
+#define B_PCI_BAR_MEMORY_TYPE_64 BIT2
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiInitPpi.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiInitPpi.h
new file mode 100644
index 0000000000..6d2b857ac6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiInitPpi.h
@@ -0,0 +1,22 @@
+/** @file
+ Silicon Initializtion PPI is used to export End of Silicon
+ init
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_INIT_PPI_H_
+#define _SI_INIT_PPI_H_
+
+extern EFI_GUID gEndOfSiInitPpiGuid;
+
+#endif // _SI_INIT_PPI_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiPolicy.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiPolicy.h
new file mode 100644
index 0000000000..044dadc022
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Ppi/SiPolicy.h
@@ -0,0 +1,36 @@
+/** @file
+ Silicon Policy PPI is used for specifying platform
+ related Intel silicon information and policy setting.
+ This PPI is consumed by the silicon PEI modules and carried
+ over to silicon DXE modules.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_POLICY_PPI_H_
+#define _SI_POLICY_PPI_H_
+
+#include <SiPolicyStruct.h>
+#include <PchAccess.h>
+#include <PchPolicyCommon.h>
+#include <PchPreMemPolicyCommon.h>
+#include <MePolicyCommon.h>
+#include <SaPolicyCommon.h>
+#include <CpuPolicyCommon.h>
+
+extern EFI_GUID gSiPreMemPolicyPpiGuid;
+extern EFI_GUID gSiPolicyPpiGuid;
+
+typedef struct _SI_PREMEM_POLICY_STRUCT SI_PREMEM_POLICY_PPI;
+typedef struct _SI_POLICY_STRUCT SI_POLICY_PPI;
+
+#endif // _SI_POLICY_PPI_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/Protocol/SiPolicyProtocol.h b/Silicon/Intel/KabylakeSiliconPkg/Include/Protocol/SiPolicyProtocol.h
new file mode 100644
index 0000000000..91fcad80a0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/Protocol/SiPolicyProtocol.h
@@ -0,0 +1,66 @@
+/** @file
+ Protocol used for specifying platform related Silicon information and policy setting.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_POLICY_PROTOCOL_H_
+#define _SI_POLICY_PROTOCOL_H_
+
+#include <IndustryStandard/Hsti.h>
+
+//
+// DXE_SI_POLICY_PROTOCOL revisions
+//
+#define DXE_SI_POLICY_PROTOCOL_REVISION 2
+
+extern EFI_GUID gDxeSiPolicyProtocolGuid;
+
+#pragma pack (push,1)
+
+/**
+ The protocol allows the platform code to publish a set of configuration information that the
+ Silicon drivers will use to configure the processor in the DXE phase.
+ This Policy Protocol needs to be initialized for Silicon configuration.
+ @note The Protocol has to be published before processor DXE drivers are dispatched.
+**/
+typedef struct {
+ /**
+ This member specifies the revision of the Si Policy protocol. This field is used to indicate backward
+ compatible changes to the protocol. Any such changes to this protocol will result in an update in the revision number.
+
+ <b>Revision 1</b>:
+ - Initial version
+ <b>Revision 2</b>:
+ - Added SmbiosOemTypeFirmwareVersionInfo to determines the SMBIOS OEM type
+ **/
+ UINT8 Revision;
+ /**
+ SmbiosOemTypeFirmwareVersionInfo determines the SMBIOS OEM type (0x80 to 0xFF) defined in SMBIOS,
+ values 0-0x7F will be treated as disable FVI reporting.
+ FVI structure uses it as SMBIOS OEM type to provide version information.
+ **/
+ UINT8 SmbiosOemTypeFirmwareVersionInfo;
+ UINT8 ReservedByte[6]; ///< Reserved bytes, align to multiple 8.
+ /**
+ This member describes a pointer to Hsti results from previous boot. In order to mitigate the large performance cost
+ of performing all of the platform security tests on each boot, we can save the results across boots and retrieve
+ and point this policy to them prior to the launch of HstiSiliconDxe. Logic should be implemented to not populate this
+ upon major platform changes (i.e changes to setup option or platform hw)to ensure that results accurately reflect the
+ configuration of the platform.
+ **/
+ ADAPTER_INFO_PLATFORM_SECURITY *Hsti; ///< This is a pointer to Hsti results from previous boot
+ UINTN HstiSize; ///< Size of results, if setting Hsti policy to point to previous results
+} DXE_SI_POLICY_PROTOCOL;
+
+#pragma pack (pop)
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Include/SiPolicyStruct.h b/Silicon/Intel/KabylakeSiliconPkg/Include/SiPolicyStruct.h
new file mode 100644
index 0000000000..f1facc4300
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Include/SiPolicyStruct.h
@@ -0,0 +1,110 @@
+/** @file
+ Intel reference code configuration policies.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_POLICY_STRUCT_H_
+#define _SI_POLICY_STRUCT_H_
+
+#include <ConfigBlock.h>
+
+/**
+ Silicon Policy revision number
+ Any change to this structure will result in an update in the revision number
+
+ This member specifies the revision of the Silicon Policy. This field is used to indicate change
+ to the policy structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+#define SI_POLICY_REVISION 1
+#define SI_CONFIG_REVISION 1
+
+/**
+ Silicon pre-memory Policy revision number
+ Any change to this structure will result in an update in the revision number
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+#define SI_PREMEM_POLICY_REVISION 1
+
+extern EFI_GUID gSiConfigGuid;
+
+/**
+ The Silicon Policy allows the platform code to publish a set of configuration
+ information that the RC drivers will use to configure the silicon hardware.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0 - 27 Config Block Header
+ //
+ // Platform specific common policies that used by several silicon components.
+ //
+ ///
+ /// Offset 28 The minimum temporary bus number available to be assigned to each root port and its downstream
+ /// devices for initialization of these devices before PCI Bus enumeration.
+ ///
+ UINT8 TempPciBusMin;
+ ///
+ /// Offset 29 The maximum temporary bus number available to be assigned to each root port and its downstream
+ /// devices for initialization of these devices before PCI Bus enumeration.
+ ///
+ UINT8 TempPciBusMax;
+ UINT8 Rsvd0[2]; ///< Offset 30 - 31 Reserved bytes, align to multiple 4.
+ ///
+ /// Offset 32 Temporary Memory Base Address for PCI devices to be used to initialize MMIO registers.
+ /// Minimum size is 2MB bytes
+ ///
+ UINT32 TempMemBaseAddr;
+ ///
+ /// Offset 36 Size of allocated temp MMIO space
+ ///
+ UINT32 TempMemSize;
+ ///
+ /// Offset 40 Temporary IO Base Address for PCI devices to be used to initialize IO registers.
+ ///
+ UINT16 TempIoBaseAddr;
+ UINT16 TempIoSize; ///< Offset 42 Size of temporary IO space
+ UINT32 CsmFlag :1; ///< Offset 44 BIT0: CSM status flag.
+ UINT32 RsvdBits :31; ///< Reserved
+} SI_CONFIG;
+
+/**
+ SI Policy PPI in Pre-Mem\n
+ All SI config block change history will be listed here\n\n
+
+ - <b>Revision 1</b>:
+ - Initial version.\n
+**/
+struct _SI_PREMEM_POLICY_STRUCT {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader;
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+};
+
+/**
+ SI Policy PPI\n
+ All SI config block change history will be listed here\n\n
+
+ - <b>Revision 1</b>:
+ - Initial version.\n
+**/
+struct _SI_POLICY_STRUCT {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader;
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/Library/PcieInitLib.h b/Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/Library/PcieInitLib.h
new file mode 100644
index 0000000000..f8c3c3b43d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/Library/PcieInitLib.h
@@ -0,0 +1,839 @@
+/** @file
+ PCIe Initialization Library header file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCIE_INIT_LIB_H_
+#define _PCIE_INIT_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PostCodeLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioLib.h>
+
+
+#ifdef PCIE_X32_SUPPORT
+#define PCIE_MAX_LANE 32
+#else
+#define PCIE_MAX_LANE 16
+#endif
+#define PCIE_ROOT_PORT_BITMAP_LENGTH 8
+#define PCIE_SWEQ_MAX_PRESETS 11
+
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND 1
+#endif
+#ifndef STALL_ONE_MILLI_SECOND
+#define STALL_ONE_MILLI_SECOND 1000
+#endif
+
+///
+/// PCIe Root Port description data structure, used as the interface between low
+/// level and high level
+///
+typedef struct {
+ UINT8 MaxCapableSpeed;
+ UINT8 MaxCapableWidth;
+ BOOLEAN EnableMargin;
+ BOOLEAN SkipMargin;
+ BOOLEAN FoundUsableTxEq;
+ UINT8 ActiveLaneListLength;
+ UINT8 ActiveLaneList[PCIE_MAX_LANE];
+} PCIE_PORT_SWEQ_DATA;
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINTN ConfigSpaceBase;
+ UINT8 PcieCapOffset;
+ UINT8 MaxPortWidth;
+ UINT8 MaxPortSpeed;
+ UINT8 MaxPortLaneListLength;
+ UINT8 MaxPortLaneList[PCIE_MAX_LANE];
+ ///
+ /// Variables below this line will only contain valid data after the PCIe link
+ /// is enabled and completes training
+ ///
+ BOOLEAN EndpointPresent;
+ UINT32 EndpointVendorIdDeviceId;
+ UINT8 EndpointMaxLinkSpeed;
+ UINT8 EndpointMaxLinkWidth;
+ PCIE_PORT_SWEQ_DATA SwEqData;
+} PCIE_PORT_INFO;
+
+///
+/// Data structure for passing static equalization data for programming
+///
+typedef struct {
+ PCIE_PORT_INFO *PciePort;
+ UINT8 RootPortPresets[PCIE_MAX_LANE];
+ UINT8 EndpointPresets[PCIE_MAX_LANE];
+ UINT8 EndpointHints[PCIE_MAX_LANE];
+} PCIE_PORT_EQS;
+
+///
+/// Input Configuration Parameters for Software Equalization Support
+///
+typedef struct {
+ BOOLEAN EnableGpioPerstSupport;
+ GPIO_PAD GpioPad;
+ BOOLEAN GpioActiveHigh;
+} PCIE_SWEQ_GPIO_CONFIG;
+
+typedef struct {
+ PCIE_PORT_INFO *PciePort;
+ UINT8 StaticEndpointPresets[PCIE_MAX_LANE];
+ UINT8 LastBootBestPresets[PCIE_MAX_LANE];
+ UINT32 LastBootEndpointVendorIdDeviceId;
+ PCIE_SWEQ_GPIO_CONFIG GpioConfig;
+ BOOLEAN EnableSwEq;
+} PCIE_SWEQ_PORT_INPUT;
+
+typedef struct {
+ PCIE_SWEQ_PORT_INPUT *PerPortInputParameters;
+ UINT8 PerPortInputParametersLength;
+ BOOLEAN HaveDataFromLastBoot;
+ UINT8 PresetsToTest[PCIE_SWEQ_MAX_PRESETS];
+ UINT8 PresetsToTestLength;
+ BOOLEAN AlwaysAttemptSwEq;
+ UINTN JitterDwellTime;
+ UINT16 JitterErrorTarget;
+ UINTN VocDwellTime;
+ UINT16 VocErrorTarget;
+ BOOLEAN EnableVocTest;
+ BOOLEAN EnableBdatScoreSchema;
+} PCIE_SWEQ_INPUT_PARAMETERS;
+
+///
+/// Data Output from Software Equalization
+///
+typedef struct {
+ INT32 MarginScore[PCIE_MAX_LANE];
+ UINT8 Preset;
+} PCIE_SWEQ_PRESET_SCORE;
+
+typedef struct {
+ PCIE_PORT_INFO *PciePort;
+ INT32 TempMarginData[PCIE_MAX_LANE];
+ UINT8 BestPresets[PCIE_MAX_LANE];
+ INT32 BestScores[PCIE_MAX_LANE];
+ PCIE_SWEQ_PRESET_SCORE PresetScores[PCIE_SWEQ_MAX_PRESETS];
+} PCIE_SWEQ_PORT_OUTPUT;
+
+typedef struct {
+ PCIE_SWEQ_PORT_OUTPUT *PortOutputList;
+ UINT8 PortOutputListLength;
+ BOOLEAN DeferredPlatformResetRequired;
+} PCIE_SWEQ_OUTPUT;
+
+typedef enum {
+ LaneLevelRxJitter,
+ PortLevelRxJitter,
+ VocCorners,
+ MarginTestTypeMax
+} MARGIN_TEST_TYPE;
+
+typedef struct _PCIE_SI_LOW_LEVEL_FUNCTION_CALLS PCIE_SI_LOW_LEVEL_FUNCTION_CALLS;
+
+///
+/// PCIe Initialization Library Generic High Level Function Calls
+///
+
+/**
+ The PCIe Software Equalization algorithm. Provides an adaptive EQ Phase 3
+ implementation in software.
+
+ @param[in] PcieAccess - Low level function table
+ @param[in] PciePorts - PCIe Root Ports to wait for
+ @param[in] PciePortsLength - Length of the PciePorts array
+ @param[in] InputParameters - Configuration options for SW EQ
+ @param[out] OutputData - The data that the algorithm generated
+**/
+VOID
+PcieGen3SoftwareEqualization (
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *PcieAccess,
+ IN PCIE_PORT_INFO *PciePorts,
+ IN UINT8 PciePortsLength,
+ IN PCIE_SWEQ_INPUT_PARAMETERS *InputParameters,
+ OUT PCIE_SWEQ_OUTPUT *OutputData
+ );
+
+/**
+ Waits for the Data Link Layer on all given root ports to reach the DL_Active state.
+ The user passes a fail mask that indicates which root ports to check. The function
+ will update the fail mask to indicate which root ports successfully trained.
+
+ The fail mask is a bitmap based on PciePorts array indices. The array must be
+ of length 8 or greater since the PciePorts array can have at most 256 entries.
+
+ @param[in] PcieAccess - Low level function table
+ @param[in] PciePorts - PCIe Root Ports to wait for
+ @param[in] PciePortsLength - Length of the PciePorts array
+ @param[in] ForceCheck - TRUE to ignore current FailMask and check all root ports
+ @param[in, out] FailMask - Bitmap of root ports to check. Returns bitmap indicating which root ports
+ failed to reach DL_Active. Array must be of length 8 or greater!
+**/
+VOID
+EFIAPI
+WaitForDataLinkLayerLinkActiveOnAllPorts (
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *PcieAccess,
+ IN PCIE_PORT_INFO *PciePorts,
+ IN UINT8 PciePortsLength,
+ IN BOOLEAN ForceCheck,
+ IN OUT UINT32 *FailMask ///< [PCIE_ROOT_PORT_BITMAP_LENGTH]
+ );
+
+/**
+ This function prints the time required for DL_Active to be set. Quits after 100 msec.
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+**/
+VOID
+WaitForDataLinkLayerLinkActive (
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *PcieAccess,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Computes the Pre-Cursor, Cursor, and Post-Cursor from a preset
+
+ @param[in] Preset - Preset to compute coefficients for
+ @param[in] FullSwing - The full swing of the transmitter
+ @param[out] PreCursor - Computed Pre-Cursor
+ @param[out] Cursor - Computed Cursor
+ @param[out] PostCursor - Computed Post-Cursor
+**/
+VOID
+GetCoefficientsFromPreset (
+ IN UINT8 Preset,
+ IN UINT8 FullSwing,
+ OUT UINT8 *PreCursor,
+ OUT UINT8 *Cursor,
+ OUT UINT8 *PostCursor
+ );
+
+/**
+ Checks for link speed and width downgrades
+
+ @param[in] PcieAccess - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] OriginalLinkSpeed - Original Speed of the Link
+ @param[in] OriginalLinkWidth - Original Width of the Link
+**/
+BOOLEAN
+LinkIsDowngraded (
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *PcieAccess,
+ IN PCIE_PORT_INFO *PciePort,
+ IN UINT8 OriginalLinkSpeed,
+ IN UINT8 OriginalLinkWidth
+ );
+
+
+///
+/// PCIe Initialization Library Generic Low Level Function Calls
+/// All of these functions can be implemented using only PCIe specification
+/// level details. However, it is possible to override the default
+/// implementation provided by this library with a Silicon Specific one if needed
+///
+
+/**
+ This function detects if an endpoint is attached to each given root port and
+ if so, reads data from the endpoint and fills in the remaining fields of the
+ PCIE_PORT_INFO structure that could not be filled before initial link training
+
+ @param[in] This - Low level function table
+ @param[out] PciePorts - Array of PCIe Root Ports
+ @param[out] PciePortsLength - Length of the PciePorts array
+**/
+typedef
+VOID
+(EFIAPI *PCIE_DETECT_ENDPOINT_PRESENCE)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePorts,
+ IN UINT8 PciePortsLength
+ );
+
+/**
+ Gets the PCIe Capability Structure Pointer
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+
+ @retval Offset to the PCIe Capability Structure
+**/
+typedef
+UINT8
+(EFIAPI *PCIE_GET_PCIE_CAP_OFFSET)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Checks if the Data Link Layer is in DL_Active state on the given root port
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - Root Port to check for DL_Active
+
+ @retval TRUE - Data Link Layer is in DL_Active state
+ @retval FALSE - Data Link Layer is NOT in DL_Active state
+**/
+typedef
+BOOLEAN
+(EFIAPI *PCIE_DATA_LINK_LAYER_LINK_ACTIVE)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Returns the current value of the PCIe Slot Status Presence Detect bit
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+
+ @retval Slot Presence Detect bit state
+**/
+typedef
+BOOLEAN
+(EFIAPI *PCIE_GET_SLOT_PRESENCE_DETECT)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Set the Link Disable bit in the PCIe Link Control Register
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] LinkDisable - New value for link disable bit
+**/
+typedef
+VOID
+(EFIAPI *PCIE_SET_LINK_DISABLE)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort,
+ IN BOOLEAN LinkDisable
+ );
+
+/**
+ Retrain the PCIe link
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+**/
+typedef
+VOID
+(EFIAPI *PCIE_RETRAIN_LINK)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Get Negotiated Link Width
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+**/
+typedef
+UINT8
+(EFIAPI *PCIE_GET_NEGOTIATED_WIDTH)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Get Current Link Speed
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+**/
+typedef
+UINT8
+(EFIAPI *PCIE_GET_CURRENT_LINK_SPEED)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+///
+/// PCIe Initialization Library Silicon Specific Low Level Function Calls
+/// Enables Abstraction of Silicon details keeping this library generic
+///
+
+/**
+ This function determines if the silicon implements the PCIe bus interface
+ that this instance of PCIE_SI_LOW_LEVEL_FUNCTION_CALLS is intended for.
+
+ @retval TRUE - Silicon supports the bus interface
+ @retval FALSE - otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *PCIE_EXISTS)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This
+ );
+
+/**
+ This function determines the topology of the PCIe bus interface that is being
+ initialized using silicon defined mechanisms. The PciePorts pointer must
+ point to a pre-allocated array which is capable of containing the maximum
+ number of root ports that this function will return. Generally this is done
+ by a component specific entrypoint that can allocate the array on the stack
+ using a fixed size appropriate for the HW. If this needs to be called from
+ generic code, the generic code must allocate a buffer that can contain 256
+ entries (which should be avoided.)
+
+ @param[in] This - Low level function table
+ @param[out] PciePorts - Array of Detected PCIe Root Ports
+ @param[out] PciePortsLength - Length of the PciePorts array
+**/
+typedef
+VOID
+(EFIAPI *PCIE_GET_ROOT_PORTS)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ OUT PCIE_PORT_INFO *PciePorts,
+ OUT UINT8 *PciePortsLength
+ );
+
+/**
+ Programs static equalization settings for the given list of PCIe root ports.
+ The PCIE_PORT_EQs structure is laid out such that the Root Port preset for
+ PHYSICAL lane number PciePortEqs->PciePort->MaxPortLaneList[0] is
+ PciePortEqs->RootPortPresets[0]. Note that physical lane numbers may not
+ start at or include zero. Package pin 0 may not be mapped to a given Root Port
+
+ @param[in] This - Low level function table
+ @param[in] PciePortEqs - Array of Root Ports + Eqs to program
+ @param[in] PciePortEqsLength - Number of Root Ports to program
+**/
+typedef
+VOID
+(EFIAPI *PCIE_PROGRAM_STATIC_GEN3_EQ)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_EQS *PciePortEqs,
+ IN UINT8 PciePortEqsLength
+ );
+
+/**
+ Sets Gen3 Equalization Phase 2 Bypass for all given Root Ports
+
+ @param[in] This - Low level function table
+ @param[in] PciePorts - PCIe Root Ports to program Phase2 for
+ @param[in] PciePortsLength - Length of the PciePorts array
+ @param[in] BypassPhase2 - TRUE to enable Phase2 bypass, FALSE otherwise
+
+ @retval EFI_SUCCESS - Phase 2 bypass was successful
+ @retval EFI_UNSUPPORTED - Hardware does not support the given Phase2 bypass request
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_SET_GEN3_PHASE2_BYPASS)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePorts,
+ IN UINT8 PciePortsLength,
+ IN BOOLEAN BypassPhase2
+ );
+
+/**
+ This function reports a PCIe controller's link status
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+**/
+typedef
+VOID
+(EFIAPI *PCIE_REPORT_LINK_STATUS)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+///
+/// PCIe Link Recovery Functions
+///
+
+/**
+ Wait until link is up.
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+
+ @retval EFI_SUCCESS - Completed successfully before timeout
+ @retval EFI_TIMEOUT - Timed out
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_WAIT_FOR_L0)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Get Target Link Speed
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+**/
+typedef
+UINT8
+(EFIAPI *PCIE_GET_TARGET_LINK_SPEED)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Set Target Link Speed
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] TargetLinkSpeed - Target Link Speed
+**/
+typedef
+VOID
+(EFIAPI *PCIE_SET_TARGET_LINK_SPEED)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort,
+ IN UINT8 TargetLinkSpeed
+ );
+
+/**
+ Resets the endpoint connected to the given root port by directly pulsing the
+ PERST# signal. The minimum assertion time, T_PERST (100 usec), is defined in
+ the PCIe CEM Specification.
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] InputParameters - SW EQ Input Parameters
+
+ @retval EFI_SUCCESS - GPIO set successfully
+ @retval EFI_UNSUPPORTED - GPIO is not supported
+ @retval EFI_INVALID_PARAMETER - GPIO pin number is invalid
+ @retval EFI_TIMEOUT - Link did not train after pulsing PERST#
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_RESET_ENDPOINT_PERST)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort,
+ IN PCIE_SWEQ_INPUT_PARAMETERS *InputParameters
+ );
+
+/**
+ This function asserts/deasserts a GPIO that controls PERST#. The minimum
+ assertion time, T_PERST (100 usec), is defined in the PCIe CEM Specification.
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] InputParameters - SW EQ Input Parameters
+ @param[in] AssertPerst - TRUE to assert PERST#, FALSE to deassert
+
+ @retval EFI_SUCCESS - GPIO set successfully
+ @retval EFI_UNSUPPORTED - GPIO is not supported
+ @retval EFI_INVALID_PARAMETER - GPIO pin number is invalid
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_SET_PERST)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort,
+ IN PCIE_SWEQ_INPUT_PARAMETERS *InputParameters,
+ IN BOOLEAN AssertPerst
+ );
+
+/**
+ Recovers a link width downgrade back to the original width. Generally this
+ doesn't need to be called directly since EnsureLinkIsHealthy() checks link
+ width in addition to other link health checks.
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] OriginalLinkWidth - Original Link Width
+
+ @retval EFI_SUCCESS - Link is running at the correct width
+ @retval EFI_DEVICE_ERROR - Unable to correct link width downgrade
+ @retval EFI_TIMEOUT - Link did not successfully retrain
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_RECOVER_LINK_WIDTH)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort,
+ IN UINT8 OriginalLinkWidth
+ );
+
+/**
+ This function sets a GPIO to a particular level.
+
+ @param[in] This - Low level function table
+ @param[in] GpioPad - PCH GPIO Pad
+ @param[in] Level - 0 = Low, 1 = High
+
+ @retval EFI_SUCCESS - GPIO set successfully
+ @retval EFI_UNSUPPORTED - GPIO is not supported
+ @retval EFI_INVALID_PARAMETER - GPIO pin number is invalid
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_SET_PCH_GPIO)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN GPIO_PAD GpioPad,
+ IN UINT8 Level
+ );
+
+/**
+ Check the status of the given PCIe link, detect and correct and downgrades
+
+ @param[in] This - Low level function table
+ @param[in] InputParameters - SW EQ Input Parameters
+ @param[in] PciePort - PCIe Root Port
+ @param[in] OriginalLinkSpeed - Expected speed of the PCIe link
+ @param[in] OriginalLinkWidth - Expected width of the PCIe link
+ @param[out] DeferredPlatformResetRequired - A platform reset is needed after saving Eq data to NVRAM
+
+ @retval EFI_SUCCESS - Link is running at the correct speed/width
+ @retval EFI_UNSUPPORTED - Unable to correct failure due to lack of GPIO PERST# support
+ @retval EFI_INVALID_PARAMETER - Unable to correct failure because the GPIO pin number is invalid
+ @retval EFI_DEVICE_ERROR - Unable to correct link downgrade
+ @retval EFI_TIMEOUT - Link did not successfully retrain
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_ENSURE_LINK_IS_HEALTHY)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_SWEQ_INPUT_PARAMETERS *InputParameters,
+ IN PCIE_PORT_INFO *PciePort,
+ IN UINT8 OriginalLinkSpeed,
+ IN UINT8 OriginalLinkWidth,
+ OUT BOOLEAN *DeferredPlatformResetRequired
+ );
+
+///
+/// PCIe Error Counting Functions
+///
+
+/**
+ Open port for monitor
+
+ @param[in] This - Low level function table
+
+ @retval Monitor Port
+**/
+typedef
+UINT32
+(EFIAPI *PCIE_OPEN_MONITOR)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This
+ );
+
+/**
+ Close port for monitor
+
+ @param[in] This - Low level function table
+ @param[in] MonitorPort - Monitor Port
+**/
+typedef
+VOID
+(EFIAPI *PCIE_CLOSE_MONITOR)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN UINT32 MonitorPort
+ );
+
+/**
+ Get Current Error Count
+
+ @param[in] This - Low level function table
+ @param[in] MonitorPort - Monitor Port
+ @param[in] PciePort - PCIe Root Port
+**/
+typedef
+UINT32
+(EFIAPI *PCIE_GET_ERROR_COUNT)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN UINT32 MonitorPort,
+ IN PCIE_PORT_INFO *PciePort
+ );
+
+/**
+ Clear Current Error Count for all Root Ports
+
+ @param[in] This - Low level function table
+ @param[in] MonitorPort - Monitor Port
+**/
+typedef
+VOID
+(EFIAPI *PCIE_CLEAR_ERROR_COUNT)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN UINT32 MonitorPort
+ );
+
+/**
+ Enable or Disable Polling Compliance Mode
+
+ @param[in] This - Low level function table
+ @param[in] PciePorts - PCIe Root Ports
+ @param[in] PciePortsLength - Length of PciePorts array
+ @param[in] Enable - TRUE to enable, FALSE to disable
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_POLLING_COMPLIANCE_MODE)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePorts,
+ IN UINT8 PciePortsLength,
+ IN BOOLEAN Enable
+ );
+
+/**
+ Program TxEQs on the endpoint attached to the given root port.
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] Presets - Array of presets to program per lane
+ must be of sufficient length to program all lanes
+**/
+typedef
+VOID
+(EFIAPI *PCIE_PROGRAM_PORT_PHASE3_TXEQ)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort,
+ IN UINT8 *Presets///[PCIE_MAX_LANE]
+ );
+
+/**
+ Program the same TxEQ to all lanes on the endpoint attached to the given root port.
+
+ @param[in] This - Low level function table
+ @param[in] PciePort - PCIe Root Port
+ @param[in] Preset - Preset to program
+**/
+typedef
+VOID
+(EFIAPI *PCIE_PROGRAM_UNIFORM_PORT_PHASE3_TXEQ)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePort,
+ IN UINT8 Preset
+ );
+
+/**
+ Runs a Margin Test on the specified root ports. The MarginData parameter must
+ be an array with capacity of PciePortsLength elements or more.
+
+ @param[in] This - Low level function table
+ @param[in] PciePorts - PCIe Root Ports to margin
+ @param[in] PciePortsLength - Length of the PciePorts array
+ @param[in] InputParameters - SW EQ Input Parameters
+ @param[in] MonitorPort - Monitor Port
+ @param[in] MarginTest - Type of Margin Test to Run
+ @param[out] MarginData - Margin Data, must be array of size >= PciePortsLength
+ @param[out] DeferredPlatformResetRequired - A platform reset is needed after saving Eq data to NVRAM
+
+ @retval EFI_SUCCESS - Margin Data Generated Successfully
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCIE_RUN_MARGIN_TEST)(
+ IN PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *This,
+ IN PCIE_PORT_INFO *PciePorts,
+ IN UINT8 PciePortsLength,
+ IN PCIE_SWEQ_INPUT_PARAMETERS *InputParameters,
+ IN UINT32 MonitorPort,
+ IN MARGIN_TEST_TYPE MarginTest,
+ OUT PCIE_SWEQ_PORT_OUTPUT *MarginData,
+ OUT BOOLEAN *DeferredPlatformResetRequired
+ );
+
+struct _PCIE_SI_LOW_LEVEL_FUNCTION_CALLS {
+ VOID *PrivateData;
+
+ ///
+ /// Generic Low Level
+ ///
+ PCIE_DETECT_ENDPOINT_PRESENCE DetectEndpointPresence;
+ PCIE_GET_PCIE_CAP_OFFSET GetPcieCapOffset;
+ PCIE_DATA_LINK_LAYER_LINK_ACTIVE DataLinkLayerLinkActive;
+ PCIE_GET_SLOT_PRESENCE_DETECT GetSlotPresenceDetect;
+ PCIE_SET_LINK_DISABLE SetLinkDisable;
+ PCIE_RETRAIN_LINK RetrainLink;
+ PCIE_GET_NEGOTIATED_WIDTH GetNegotiatedWidth;
+ PCIE_GET_CURRENT_LINK_SPEED GetCurrentLinkSpeed;
+ PCIE_GET_TARGET_LINK_SPEED GetTargetLinkSpeed;
+ PCIE_SET_TARGET_LINK_SPEED SetTargetLinkSpeed;
+ PCIE_SET_PERST SetPerst;
+ PCIE_ENSURE_LINK_IS_HEALTHY EnsureLinkIsHealthy;
+
+ ///
+ /// Silicon Specific Low Level
+ ///
+ PCIE_EXISTS PcieExists;
+ PCIE_GET_ROOT_PORTS GetPcieRootPorts;
+ PCIE_PROGRAM_STATIC_GEN3_EQ ProgramStaticGen3Eq;
+ PCIE_SET_GEN3_PHASE2_BYPASS SetPhase2Bypass;
+ PCIE_REPORT_LINK_STATUS ReportPcieLinkStatus;
+ PCIE_WAIT_FOR_L0 WaitForL0;
+ PCIE_RESET_ENDPOINT_PERST ResetEndpointPerst;
+ PCIE_RECOVER_LINK_WIDTH RecoverLinkWidth;
+ PCIE_SET_PCH_GPIO SetPchGpio;
+ PCIE_OPEN_MONITOR OpenMonitor;
+ PCIE_CLOSE_MONITOR CloseMonitor;
+ PCIE_GET_ERROR_COUNT GetErrorCount;
+ PCIE_CLEAR_ERROR_COUNT ClearErrorCount;
+ PCIE_POLLING_COMPLIANCE_MODE PollingComplianceMode;
+ PCIE_PROGRAM_PORT_PHASE3_TXEQ ProgramPortPhase3TxEq;
+ PCIE_PROGRAM_UNIFORM_PORT_PHASE3_TXEQ ProgramUniformPortPhase3TxEq;
+ PCIE_RUN_MARGIN_TEST RunMarginTest;
+};
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ - 0x01 = PCI Power Management Interface
+ - 0x04 = Slot Identification
+ - 0x05 = MSI Capability
+ - 0x10 = PCI Express Capability
+
+ @param[in] Bus - PCI Bus Number
+ @param[in] Device - PCI Device Number
+ @param[in] Function - PCI Function Number
+ @param[in] CapId - CAPID to search for
+
+ @retval 0 - CAPID not found
+ @retval Other - CAPID found, Offset of desired CAPID
+**/
+UINT32
+PcieLibFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ );
+
+/**
+ This function gets the table of generic low level function calls for the PCIe
+ interface. These function calls use PCIe spec defined mechanisms and can be
+ overrided by a silicon specific implementation if needed.
+
+ @param[out] PcieLowLevel - Table of function calls for PCIe
+
+ @retval EFI_SUCCESS - Table of function calls returned successfully
+**/
+EFI_STATUS
+GetGenericPcieLowLevelFunctionCalls (
+ OUT PCIE_SI_LOW_LEVEL_FUNCTION_CALLS *PcieLowLevelFunctionCalls
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/SiConfigHob.h b/Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/SiConfigHob.h
new file mode 100644
index 0000000000..676e5e433b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/IncludePrivate/SiConfigHob.h
@@ -0,0 +1,24 @@
+/** @file
+ Silicon Config HOB is used for gathering platform
+ related Intel silicon information and config setting.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_CONFIG_HOB_H_
+#define _SI_CONFIG_HOB_H_
+
+#include <SiPolicyStruct.h>
+
+extern EFI_GUID gSiConfigHobGuid;
+
+typedef CONST SI_CONFIG SI_CONFIG_HOB;
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconBuild.bat b/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconBuild.bat
new file mode 100644
index 0000000000..98d94cf310
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconBuild.bat
@@ -0,0 +1,62 @@
+@REM @file
+@REM
+@REM Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+@REM This program and the accompanying materials
+@REM are licensed and made available under the terms and conditions of the BSD License
+@REM which accompanies this distribution. The full text of the license may be found at
+@REM http://opensource.org/licenses/bsd-license.php
+@REM
+@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+@REM
+
+@call edksetup.bat
+
+@if not defined TOOL_CHAIN_TAG (
+ if defined VS140COMNTOOLS (
+ echo.
+ echo Prebuild: Set the VS2015 environment.
+ echo.
+ if not defined VSINSTALLDIR call "%VS140COMNTOOLS%\vsvars32.bat"
+ if /I "%VS140COMNTOOLS%" == "C:\Program Files\Microsoft Visual Studio 14.0\Common7\Tools\" (
+ set TOOL_CHAIN_TAG=VS2015
+ ) else (
+ set TOOL_CHAIN_TAG=VS2015x86
+ )
+ )
+)
+
+@if not defined TOOL_CHAIN_TAG (
+ if defined VS120COMNTOOLS (
+ echo.
+ echo Prebuild: Set the VS2013 environment.
+ echo.
+ if not defined VSINSTALLDIR call "%VS120COMNTOOLS%\vsvars32.bat"
+ if /I "%VS120COMNTOOLS%" == "C:\Program Files\Microsoft Visual Studio 12.0\Common7\Tools\" (
+ set TOOL_CHAIN_TAG=VS2013
+ ) else (
+ set TOOL_CHAIN_TAG=VS2013x86
+ )
+ )
+)
+
+set TARGET=RELEASE
+
+@echo.
+@echo Set build environment.
+@echo.
+@if not exist Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG% (
+ mkdir Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG%
+)
+
+
+@findstr /V "ACTIVE_PLATFORM TARGET TARGET_ARCH TOOL_CHAIN_TAG BUILD_RULE_CONF" Conf\target.txt > Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt
+@echo ACTIVE_PLATFORM = KabylakeSiliconPkg/KabylakeSiliconPkg.dsc >> Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG%\target.txt
+@echo TARGET = %TARGET% >> Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG%\target.txt
+@echo TARGET_ARCH = IA32 X64 >> Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG%\target.txt
+@echo TOOL_CHAIN_TAG = %TOOL_CHAIN_TAG% >> Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG%\target.txt
+@echo BUILD_RULE_CONF = Conf/build_rule.txt >> Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG%\target.txt
+@move /Y Build\KabylakeSiliconPkg\%TARGET%_%TOOL_CHAIN_TAG%\target.txt Conf
+
+build
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPkg.dsc b/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPkg.dsc
new file mode 100644
index 0000000000..7189ce6396
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPkg.dsc
@@ -0,0 +1,203 @@
+## @file
+# Component description file for the SkyLake SiPkg DSC file.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[PcdsFeatureFlag]
+gSiPkgTokenSpaceGuid.PcdTraceHubEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdSmmVariableEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSerialGpioEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdAtaEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdSiCsmEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdUseHpetTimer |FALSE
+gSiPkgTokenSpaceGuid.PcdSgEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdAcpiEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdSourceDebugEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdPpmEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdTxtEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdIntegratedTouchEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdAmtEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdPttEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdJhiEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdSoftwareGuardEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdSmbiosEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdS3Enable |TRUE
+gSiPkgTokenSpaceGuid.PcdOverclockEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdCpuPowerOnConfigEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdBdatEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSsaFlagEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdEvLoaderEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdIgdEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdPegEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSaDmiEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSkycamEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdGmmEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSaOcEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdVtdEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdBiosGuardEnable |TRUE #BiosGuardModule.bin
+gSiPkgTokenSpaceGuid.PcdOptimizeCompilerEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdPeiDisplayEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdOcWdtEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdBootGuardEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdMinTreeEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdSiCatalogDebugEnable |FALSE
+
+[PcdsFixedAtBuild.common]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress |0xE0000000
+gSiPkgTokenSpaceGuid.PcdPciExpressRegionLength |0x10000000
+
+[Defines]
+ PLATFORM_NAME = KabylakeSiliconPkg
+ PLATFORM_GUID = A45CA44C-AB04-4932-A77C-5A7179F66A22
+ PLATFORM_VERSION = 0.4
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/KabylakeSiliconPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+
+ DEFINE PLATFORM_SI_PACKAGE = KabylakeSiliconPkg
+
+ #
+ # Definition for Build Flag
+ #
+ !include $(PLATFORM_SI_PACKAGE)/SiPkgBuildOption.dsc
+
+[LibraryClasses.common]
+ #
+ # Entry point
+ #
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+
+ #
+ # Basic
+ #
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ BasePciLibPciExpress|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ #
+ # UEFI & PI
+ #
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+
+ S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf
+ S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf
+ S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf
+
+ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+ #
+ # Misc
+ #
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ PostCodeLib|MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
+ SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
+
+#####################################################################################################
+
+#
+# Silicon Init Common Library
+#
+!include $(PLATFORM_SI_PACKAGE)/SiPkgCommonLib.dsc
+
+[LibraryClasses.IA32]
+#
+# PEI phase common
+#
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+
+#####################################################################################################################################
+
+#
+# Silicon Init Pei Library
+#
+!include $(PLATFORM_SI_PACKAGE)/SiPkgPeiLib.dsc
+
+[LibraryClasses.IA32.SEC]
+
+[LibraryClasses.X64]
+ #
+ # DXE phase common
+ #
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+
+ Tpm2CommandLib|$(PLATFORM_SI_PACKAGE)/SampleCode/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
+ Tpm2DeviceLib|$(PLATFORM_SI_PACKAGE)/SampleCode/SecurityPkg/Library/Tpm2DeviceLibTrEE/Tpm2DeviceLibTrEE.inf
+
+###################################################################################################
+#
+# Silicon Init Dxe Library
+#
+!include $(PLATFORM_SI_PACKAGE)/SiPkgDxeLib.dsc
+
+[LibraryClasses.X64.PEIM]
+
+[LibraryClasses.X64.DXE_CORE]
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+
+[LibraryClasses.X64.DXE_SMM_DRIVER]
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+
+[LibraryClasses.X64.SMM_CORE]
+
+[LibraryClasses.X64.UEFI_DRIVER]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+
+[LibraryClasses.X64.UEFI_APPLICATION]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+
+[Components.IA32]
+!include $(PLATFORM_SI_PACKAGE)/SiPkgPei.dsc
+
+[Components.X64]
+!include $(PLATFORM_SI_PACKAGE)/SiPkgDxe.dsc
diff --git a/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPrivate.dec b/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
new file mode 100644
index 0000000000..163bd429f8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
@@ -0,0 +1,143 @@
+## @file
+# Component description file for the Kabylake Private DEC file.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = KabylakeSiliconPrivate
+ PACKAGE_GUID = DD6CB7A8-32F8-4170-8267-942093A5E5F6
+ PACKAGE_VERSION = 0.1
+
+[Includes.common]
+
+[Ppis]
+ #
+ # PCH
+ #
+ gPchPmcXramOffsetDataPpiGuid = { 0xc1392859, 0x1f65, 0x446e, { 0xa3, 0xf6, 0x85, 0x36, 0xfc, 0xc7, 0xd1, 0xc4 }}
+
+[LibraryClasses]
+ #
+ # Common
+ #
+ PcieInitLib|KabylakeSiliconPkg/IncludePrivate/Library/PcieInitLib.h
+ SiFviInitLib|KabylakeSiliconPkg/IncludePrivate/Library/SiFviInitLib.h
+
+ #
+ # CPU
+ #
+ BiosGuardLib|Cpu/IncludePrivate/Library/BiosGuardInit.h
+ CpuCommonLib|Cpu/IncludePrivate/Library/CpuCommonLib.h
+ CpuInitLib|Cpu/IncludePrivate/Library/CpuInitLib.h
+ CpuOcLib|Cpu/IncludePrivate/Library/CpuOcLib.h
+ CpuPowerOnConfigLib|Cpu/IncludePrivate/Library/CpuPowerOnConfigLib.h
+ CpuS3Lib|Cpu/IncludePrivate/Library/CpuS3Lib.h
+ SmbiosCpuLib|Cpu/IncludePrivate/Library/SmbiosCpuLib.h
+ SoftwareGuardLib|Cpu/IncludePrivate/Library/SoftwareGuardLib.h
+ PeiTxtLib|Cpu/IncludePrivate/Library/TxtPeiLib.h
+
+ #
+ # PCH
+ #
+ PchHdaLib|Pch/IncludePrivate/Library/DxePchHdaNhlt.h
+ GpioPrivateLib|Pch/IncludePrivate/Library/GpioPrivateLib.h
+ I2cMasterCommonLib|Pch/IncludePrivate/Library/I2cMasterCommonLib.h
+ PchAlternateAccessModeLib|Pch/IncludePrivate/Library/PchAlternateAccessModeLib.h
+ PchHdaLib|Pch/IncludePrivate/Library/PchHdaLib.h
+ PchInitCommonLib|Pch/IncludePrivate/Library/PchInitCommonLib.h
+ PchInitLib|Pch/IncludePrivate/Library/PchInitLib.h
+ PchPciExpressHelpersLib|Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h
+ PchRcLib|Pch/IncludePrivate/Library/PchRcLib.h
+ PchSmbusCommonLib|Pch/IncludePrivate/Library/PchSmbusCommonLib.h
+ PchSpiCommonLib|Pch/IncludePrivate/Library/PchSpiCommonLib.h
+ PchXhciLib|Pch/IncludePrivate/Library/PchXhciLib.h
+ PeiI2cMasterLib|Pch/IncludePrivate/Library/PeiI2cMasterLib.h
+ PchPsfPrivateLib|Pch/IncludePrivate/Library/PchPsfPrivateLib.h
+ RstPrivateLib|Pch/IncludePrivate/Library/RstPrivateLib.h
+
+ #
+ # SystemAgent
+ #
+ GmmInitLib|SystemAgent/IncludePrivate/Library/GmmInitLib.h
+ GraphicsInitLib|SystemAgent/IncludePrivate/Library/GraphicsInitLib.h
+ SaDmiInitLib|SystemAgent/IncludePrivate/Library/SaDmiInitLib.h
+ SaInitLib|SystemAgent/IncludePrivate/Library/SaPcieLib.h
+ SaOcInitLib|SystemAgent/IncludePrivate/Library/SaOcInitLib.h
+ SaPcieDmiLib|SystemAgent/IncludePrivate/Library/SaPcieDmiLib.h
+ SaPcieInitLib|SystemAgent/IncludePrivate/Library/SaPcieInitLib.h
+ SaPcieLib|SystemAgent/IncludePrivate/Library/SaPcieLib.h
+ SkyCamInitLib|SystemAgent/IncludePrivate/Library/SkyCamInitLib.h
+ SmbiosMemoryLib|SystemAgent/IncludePrivate/Library/SmbiosMemoryLib.h
+ SwitchableGraphicsInitLib|SystemAgent/IncludePrivate/Library/SwitchableGraphicsInitLib.h
+ VtdInitLib|SystemAgent/IncludePrivate/Library/VtdInitLib.h
+
+ #
+ # Me
+ #
+ ActiveManagementLib|Me/IncludePrivate/Library/ActiveManagementLib.h
+ AlertStandardFormatLib|Me/IncludePrivate/Library/AlertStandardFormatLib.h
+ DxeBeihaiLib|Me/IncludePrivate/Library/DxeBeihaiLib.h
+ DxeJhiSupportLib|Me/IncludePrivate/Library/DxeJhiSupportLib.h
+ HeciInitLib|Me/IncludePrivate/Library/HeciInitLib.h
+ MeInitLib|Me/IncludePrivate/Library/MeInitLib.h
+
+[Guids]
+ ##
+ ## Common
+ ##
+ gSiConfigHobGuid = {0xb3903068, 0x7482, 0x4424, {0xba, 0x4b, 0x40, 0x5f, 0x8f, 0xd7, 0x65, 0x4e}}
+
+ #
+ # PCH
+ #
+ gPchDeviceTableHobGuid = { 0xb3e123d0, 0x7a1e, 0x4db4, { 0xaf, 0x66, 0xbe, 0xd4, 0x1e, 0x9c, 0x66, 0x38 }}
+ gWdtHobGuid = { 0x65675786, 0xacca, 0x4b11, { 0x8a, 0xb7, 0xf8, 0x43, 0xaa, 0x2a, 0x8b, 0xea }}
+ gPchConfigHobGuid = { 0x524ed3ca, 0xb250, 0x49f5, { 0x94, 0xd9, 0xa2, 0xba, 0xff, 0xc7, 0x0e, 0x14 }}
+
+ #
+ # CPU
+ #
+ gPeiAcpiCpuDataGuid = { 0x7682bbef, 0xb0b6, 0x4939, { 0xae, 0x66, 0x1b, 0x3d, 0xf2, 0xf6, 0xaa, 0xf3 }}
+ gCpuStatusCodeDataTypeExceptionHandlerGuid = { 0x3BC2BD12, 0xAD2E, 0x11D5, { 0x87, 0xDD, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 }}
+
+ #
+ # SA
+ #
+ gTpmRegInfoHobGuid = { 0x558a4a27, 0x9343, 0x4116, { 0xa9, 0xe, 0xf5, 0xd7, 0xee, 0x81, 0xbb, 0x9b }}
+ gSchemaListGuid = { 0x3047C2AC, 0x5E8E, 0x4C55, { 0xA1, 0xCB, 0xEA, 0xAD, 0x0A, 0x88, 0x86, 0x1B }}
+ gEqPhase3SchemaGuid = { 0x145AC084, 0x340E, 0x4777, { 0xBC, 0x75, 0xF8, 0x50, 0x5F, 0xFD, 0x50, 0x9D }}
+ gScoreSchemaGuid = { 0x8233A1BB, 0x58D5, 0x4F66, { 0xA1, 0x3F, 0x8A, 0xA3, 0xED, 0x6A, 0xF5, 0xA0 }}
+ gPortMarginGuid = { 0xD7154D12, 0x03B2, 0x4054, { 0x8C, 0xD2, 0x9F, 0x4B, 0x20, 0x90, 0xBE, 0xF7 }}
+ gJitterTolerenceGuid = { 0xB52A2E04, 0x45FF, 0x484E, { 0xB5, 0xFE, 0xEE, 0x47, 0x8F, 0x5F, 0x6C, 0x9B }}
+ gLaneMarginGuid = { 0x7AC0996D, 0xA601, 0x4210, { 0x94, 0x4E, 0x93, 0x4E, 0x51, 0x7B, 0x6C, 0x57 }}
+ gVocMarginGuid = { 0x3578349A, 0x9E98, 0x4F70, { 0x91, 0xCB, 0xE2, 0x5B, 0x98, 0x99, 0xBC, 0x16 }}
+
+[Protocols]
+ #
+ # PCH
+ #
+ gPchPcieIoTrapProtocolGuid = { 0xd66a1cf, 0x79ad, 0x494b, { 0x97, 0x8b, 0xb2, 0x59, 0x81, 0x68, 0x93, 0x34 }}
+
+ #
+ # SA
+ #
+ gSaIotrapSmiProtocolGuid = { 0x1861e089, 0xcaa3, 0x473e, { 0x84, 0x32, 0xdc, 0x1f, 0x94, 0xc6, 0xc1, 0xa6 }}
+
+ #
+ # CPU
+ #
+ gPowerMgmtInitDoneProtocolGuid = {0xd71db106, 0xe32d, 0x4225, {0xbf, 0xf4, 0xde, 0x6d, 0x77, 0x87, 0x17, 0x61}}
+
+[Ppis]
+gEndOfSiInitPpiGuid = { 0xE2E3D5D1, 0x8356, 0x4F96, { 0x9C, 0x9E, 0x2E, 0xC3, 0x48, 0x1D, 0xEA, 0x88 }}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c
new file mode 100644
index 0000000000..a411547ccb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c
@@ -0,0 +1,151 @@
+/** @file
+ Library functions for Config Block management.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ Create config block table
+
+ @param[in] TotalSize - Max size to be allocated for the Config Block Table
+ @param[out] ConfigBlockTableAddress - On return, points to a pointer to the beginning of Config Block Table Address
+
+ @retval EFI_INVALID_PARAMETER - Invalid Parameter
+ @retval EFI_OUT_OF_RESOURCES - Out of resources
+ @retval EFI_SUCCESS - Successfully created Config Block Table at ConfigBlockTableAddress
+**/
+EFI_STATUS
+EFIAPI
+CreateConfigBlockTable (
+ IN UINT16 TotalSize,
+ OUT VOID **ConfigBlockTableAddress
+ )
+{
+ CONFIG_BLOCK_TABLE_HEADER *ConfigBlkTblAddrPtr;
+ UINT32 ConfigBlkTblHdrSize;
+
+ ConfigBlkTblHdrSize = (UINT32)(sizeof (CONFIG_BLOCK_TABLE_HEADER));
+
+ if (TotalSize <= (ConfigBlkTblHdrSize + sizeof (CONFIG_BLOCK_HEADER))) {
+ DEBUG ((DEBUG_ERROR, "Invalid Parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ConfigBlkTblAddrPtr = (CONFIG_BLOCK_TABLE_HEADER *)AllocateZeroPool (TotalSize);
+ if (ConfigBlkTblAddrPtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "Could not allocate memory.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ConfigBlkTblAddrPtr->NumberOfBlocks = 0;
+ ConfigBlkTblAddrPtr->Header.GuidHob.Header.HobLength = TotalSize;
+ ConfigBlkTblAddrPtr->AvailableSize = TotalSize - ConfigBlkTblHdrSize;
+
+ *ConfigBlockTableAddress = (VOID *)ConfigBlkTblAddrPtr;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add config block into config block table structure
+
+ @param[in] ConfigBlockTableAddress - A pointer to the beginning of Config Block Table Address
+ @param[out] ConfigBlockAddress - On return, points to a pointer to the beginning of Config Block Address
+
+ @retval EFI_OUT_OF_RESOURCES - Config Block Table is full and cannot add new Config Block or
+ Config Block Offset Table is full and cannot add new Config Block.
+ @retval EFI_SUCCESS - Successfully added Config Block
+**/
+EFI_STATUS
+EFIAPI
+AddConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ OUT VOID **ConfigBlockAddress
+ )
+{
+ CONFIG_BLOCK *TempConfigBlk;
+ CONFIG_BLOCK_TABLE_HEADER *ConfigBlkTblAddrPtr;
+ CONFIG_BLOCK *ConfigBlkAddrPtr;
+ UINT16 ConfigBlkSize;
+
+ ConfigBlkTblAddrPtr = (CONFIG_BLOCK_TABLE_HEADER *)ConfigBlockTableAddress;
+ ConfigBlkAddrPtr = (CONFIG_BLOCK *)(*ConfigBlockAddress);
+ ConfigBlkSize = ConfigBlkAddrPtr->Header.GuidHob.Header.HobLength;
+ DEBUG ((DEBUG_INFO, "Config Block GUID: %g / Config Block Size: 0x%x bytes\n", &(ConfigBlkAddrPtr->Header.GuidHob.Name), ConfigBlkSize));
+ if ((ConfigBlkSize % 4) != 0) {
+ DEBUG ((DEBUG_ERROR, "Config Block must be multiples of 4 bytes\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ConfigBlkTblAddrPtr->AvailableSize < ConfigBlkSize) {
+ DEBUG ((DEBUG_ERROR, "Config Block Table is full and cannot add new Config Block.\n"));
+ DEBUG ((DEBUG_ERROR, "Available Config Block Size: 0x%x bytes / Requested Config Block Size: 0x%x bytes\n", ConfigBlkTblAddrPtr->AvailableSize, ConfigBlkSize));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TempConfigBlk = (CONFIG_BLOCK *)((UINTN)ConfigBlkTblAddrPtr + (UINTN)(ConfigBlkTblAddrPtr->Header.GuidHob.Header.HobLength - ConfigBlkTblAddrPtr->AvailableSize));
+ CopyMem (&TempConfigBlk->Header, &ConfigBlkAddrPtr->Header, sizeof(CONFIG_BLOCK_HEADER));
+
+ ConfigBlkTblAddrPtr->NumberOfBlocks++;
+ ConfigBlkTblAddrPtr->AvailableSize = ConfigBlkTblAddrPtr->AvailableSize - ConfigBlkSize;
+
+ *ConfigBlockAddress = (VOID *) TempConfigBlk;
+ DEBUG ((DEBUG_INFO, "Config Block Address: 0x%x / Available Config Block Size: 0x%x bytes\n", (UINT32)(UINTN)*ConfigBlockAddress, ConfigBlkTblAddrPtr->AvailableSize));
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieve a specific Config Block data by GUID
+
+ @param[in] ConfigBlockTableAddress - A pointer to the beginning of Config Block Table Address
+ @param[in] ConfigBlockGuid - A pointer to the GUID uses to search specific Config Block
+ @param[out] ConfigBlockAddress - On return, points to a pointer to the beginning of Config Block Address
+
+ @retval EFI_NOT_FOUND - Could not find the Config Block
+ @retval EFI_SUCCESS - Config Block found and return
+**/
+EFI_STATUS
+EFIAPI
+GetConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ IN EFI_GUID *ConfigBlockGuid,
+ OUT VOID **ConfigBlockAddress
+ )
+{
+ UINT16 OffsetIndex;
+ CONFIG_BLOCK *TempConfigBlk;
+ CONFIG_BLOCK_TABLE_HEADER *ConfigBlkTblAddrPtr;
+ UINT32 ConfigBlkTblHdrSize;
+ UINT32 ConfigBlkOffset;
+ UINT16 NumOfBlocks;
+
+ ConfigBlkTblHdrSize = (UINT32)(sizeof (CONFIG_BLOCK_TABLE_HEADER));
+ ConfigBlkTblAddrPtr = (CONFIG_BLOCK_TABLE_HEADER *)ConfigBlockTableAddress;
+ NumOfBlocks = ConfigBlkTblAddrPtr->NumberOfBlocks;
+
+ ConfigBlkOffset = 0;
+ for (OffsetIndex = 0; OffsetIndex < NumOfBlocks; OffsetIndex++) {
+ if ((ConfigBlkTblHdrSize + ConfigBlkOffset) > (ConfigBlkTblAddrPtr->Header.GuidHob.Header.HobLength)) {
+ break;
+ }
+ TempConfigBlk = (CONFIG_BLOCK *)((UINTN)ConfigBlkTblAddrPtr + (UINTN)ConfigBlkTblHdrSize + (UINTN)ConfigBlkOffset);
+ if (CompareGuid (&(TempConfigBlk->Header.GuidHob.Name), ConfigBlockGuid)) {
+ *ConfigBlockAddress = (VOID *)TempConfigBlk;
+ return EFI_SUCCESS;
+ }
+ ConfigBlkOffset = ConfigBlkOffset + TempConfigBlk->Header.GuidHob.Header.HobLength;
+ }
+ DEBUG ((DEBUG_ERROR, "Could not find the config block.\n"));
+ return EFI_NOT_FOUND;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf
new file mode 100644
index 0000000000..f544c75a6c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component INF file for the BaseConfigBlock library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseConfigBlockLib
+FILE_GUID = 1EC07EA8-7808-4e06-9D79-309AE331D2D5
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+BaseConfigBlockLib.c
+
+[LibraryClasses]
+DebugLib
+BaseMemoryLib
+MemoryAllocationLib
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
new file mode 100644
index 0000000000..98ff9e3410
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
@@ -0,0 +1,93 @@
+/** @file
+ This file is BaseSiConfigBlockLib library is used to add config blocks
+ to config block header.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <ConfigBlock.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+
+
+/**
+ GetComponentConfigBlockTotalSize get config block table total size.
+
+ @param[in] ComponentBlocks Component blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval Size of config block table
+**/
+UINT16
+EFIAPI
+GetComponentConfigBlockTotalSize (
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ )
+{
+ UINT16 TotalBlockSize;
+ UINT16 BlockCount;
+
+ TotalBlockSize = 0;
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ TotalBlockSize += (UINT32) ComponentBlocks[BlockCount].Size;
+ DEBUG ((DEBUG_INFO, "TotalBlockSize after adding Block[0x%x]= 0x%x\n", BlockCount, TotalBlockSize));
+ }
+
+ return TotalBlockSize;
+}
+
+/**
+ AddComponentConfigBlocks add all config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add config blocks
+ @param[in] ComponentBlocks Config blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+AddComponentConfigBlocks (
+ IN VOID *ConfigBlockTableAddress,
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ )
+{
+ UINT16 BlockCount;
+ VOID *ConfigBlockPointer;
+ CONFIG_BLOCK ConfigBlockBuf;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Initialize ConfigBlockPointer to NULL
+ //
+ ConfigBlockPointer = NULL;
+ //
+ // Loop to identify each config block from ComponentBlocks[] Table and add each of them
+ //
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ ZeroMem (&ConfigBlockBuf,sizeof(CONFIG_BLOCK));
+ CopyMem (&(ConfigBlockBuf.Header.GuidHob.Name), ComponentBlocks[BlockCount].Guid, sizeof (EFI_GUID));
+ ConfigBlockBuf.Header.GuidHob.Header.HobLength = ComponentBlocks[BlockCount].Size;
+ ConfigBlockBuf.Header.Revision = ComponentBlocks[BlockCount].Revision;
+ ConfigBlockPointer = (VOID *)&ConfigBlockBuf;
+ Status = AddConfigBlock ((VOID *)ConfigBlockTableAddress, (VOID *)&ConfigBlockPointer);
+ ASSERT_EFI_ERROR (Status);
+ ComponentBlocks[BlockCount].LoadDefault (ConfigBlockPointer);
+ }
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
new file mode 100644
index 0000000000..5961b1a6b2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for the BaseSiConfigBlockLib library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiConfigBlockLib
+FILE_GUID = 6C068D0F-F48E-48CB-B369-433E507AF4A2
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiConfigBlockLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseSiConfigBlockLib.c
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c
new file mode 100644
index 0000000000..ea85be4a11
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c
@@ -0,0 +1,314 @@
+/** @file
+ Boot service DXE ASL update library implementation.
+
+ These functions in this file can be called during DXE and cannot be called during runtime
+ or in SMM which should use a RT or SMM library.
+
+ This library uses the ACPI Support protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Library/AslUpdateLib.h>
+
+//
+// Function implemenations
+//
+static EFI_ACPI_SDT_PROTOCOL *mAcpiSdt = NULL;
+static EFI_ACPI_TABLE_PROTOCOL *mAcpiTable = NULL;
+
+/**
+ Initialize the ASL update library state.
+ This must be called prior to invoking other library functions.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+InitializeAslUpdateLib (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Locate ACPI tables
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **) &mAcpiSdt);
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &mAcpiTable);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+
+/**
+ This procedure will update immediate value assigned to a Name
+
+ @param[in] AslSignature - The signature of Operation Region that we want to update.
+ @param[in] Buffer - source of data to be written over original aml
+ @param[in] Length - length of data to be overwritten
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+UpdateNameAslCode (
+ IN UINT32 AslSignature,
+ IN VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ UINT8 *CurrPtr;
+ UINT32 *Signature;
+ UINT8 *DsdtPointer;
+ UINTN Handle;
+ UINT8 DataSize;
+
+ if (mAcpiTable == NULL) {
+ InitializeAslUpdateLib ();
+ if (mAcpiTable == NULL) {
+ return EFI_NOT_READY;
+ }
+ }
+
+ ///
+ /// Locate table with matching ID
+ ///
+ Handle = 0;
+ Status = LocateAcpiTableBySignature (
+ EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ (EFI_ACPI_DESCRIPTION_HEADER **) &Table,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Point to the beginning of the DSDT table
+ ///
+ CurrPtr = (UINT8 *) Table;
+
+ ///
+ /// Loop through the ASL looking for values that we must fix up.
+ ///
+ for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {
+ ///
+ /// Get a pointer to compare for signature
+ ///
+ Signature = (UINT32 *) DsdtPointer;
+ ///
+ /// Check if this is the Device Object signature we are looking for
+ ///
+ if ((*Signature) == AslSignature) {
+ ///
+ /// Look for Name Encoding
+ ///
+ if (*(DsdtPointer-1) == AML_NAME_OP) {
+ ///
+ /// Check if size of new and old data is the same
+ ///
+ DataSize = *(DsdtPointer+4);
+ if ((Length == 1 && DataSize == 0xA) ||
+ (Length == 2 && DataSize == 0xB) ||
+ (Length == 4 && DataSize == 0xC)) {
+ CopyMem (DsdtPointer+5, Buffer, Length);
+ } else if (Length == 1 && ((*(UINT8*) Buffer) == 0 || (*(UINT8*) Buffer) == 1) && (DataSize == 0 || DataSize == 1)) {
+ CopyMem (DsdtPointer+4, Buffer, Length);
+ } else {
+ FreePool (Table);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ Status = mAcpiTable->UninstallAcpiTable (
+ mAcpiTable,
+ Handle
+ );
+ Handle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ Table,
+ Table->Length,
+ &Handle
+ );
+ FreePool (Table);
+ return Status;
+ }
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ This function uses the ACPI SDT protocol to locate an ACPI table.
+ It is really only useful for finding tables that only have a single instance,
+ e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc.
+
+ @param[in] Signature - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in, out] Table - Updated with a pointer to the table
+ @param[in, out] Handle - AcpiSupport protocol table handle for the table found
+ @param[in, out] Version - The version of the table desired
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableBySignature (
+ IN UINT32 Signature,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ )
+{
+ EFI_STATUS Status;
+ INTN Index;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_DESCRIPTION_HEADER *OrgTable;
+
+ if (mAcpiSdt == NULL) {
+ InitializeAslUpdateLib ();
+ if (mAcpiSdt == NULL) {
+ return EFI_NOT_READY;
+ }
+ }
+
+ ///
+ /// Locate table with matching ID
+ ///
+ Version = 0;
+ Index = 0;
+ do {
+ Status = mAcpiSdt->GetAcpiTable (Index, (EFI_ACPI_SDT_HEADER **)&OrgTable, &Version, Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (OrgTable->Signature != Signature);
+
+ if (Status != EFI_NOT_FOUND) {
+ *Table = AllocateCopyPool (OrgTable->Length, OrgTable);
+ ASSERT (*Table);
+ }
+
+ ///
+ /// If we found the table, there will be no error.
+ ///
+ return Status;
+}
+
+/**
+ This function uses the ACPI SDT protocol to locate an ACPI SSDT table.
+
+ @param[in] TableId - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in] TableIdSize - Length of the TableId to match. Table ID are 8 bytes long, this function
+ will consider it a match if the first TableIdSize bytes match
+ @param[in, out] Table - Updated with a pointer to the table
+ @param[in, out] Handle - AcpiSupport protocol table handle for the table found
+ @param[in, out] Version - See AcpiSupport protocol, GetAcpiTable function for use
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableByOemTableId (
+ IN UINT8 *TableId,
+ IN UINT8 TableIdSize,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ )
+{
+ EFI_STATUS Status;
+ INTN Index;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_DESCRIPTION_HEADER *OrgTable;
+
+ if (mAcpiSdt == NULL) {
+ InitializeAslUpdateLib ();
+ if (mAcpiSdt == NULL) {
+ return EFI_NOT_READY;
+ }
+ }
+ ///
+ /// Locate table with matching ID
+ ///
+ Version = 0;
+ Index = 0;
+ do {
+ Status = mAcpiSdt->GetAcpiTable (Index, (EFI_ACPI_SDT_HEADER **)&OrgTable, &Version, Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (CompareMem (&(OrgTable->OemTableId), TableId, TableIdSize));
+
+ if (Status != EFI_NOT_FOUND) {
+ *Table = AllocateCopyPool (OrgTable->Length, OrgTable);
+ ASSERT (*Table);
+ }
+
+ ///
+ /// If we found the table, there will be no error.
+ ///
+ return Status;
+}
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param[in] Buffer Pointer to buffer to checksum
+ @param[in] Size Number of bytes to checksum
+ @param[in] ChecksumOffset Offset to place the checksum result in
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+AcpiChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ )
+{
+ UINT8 Sum;
+ UINT8 *Ptr;
+
+ Sum = 0;
+ ///
+ /// Initialize pointer
+ ///
+ Ptr = Buffer;
+
+ ///
+ /// set checksum to 0 first
+ ///
+ Ptr[ChecksumOffset] = 0;
+
+ ///
+ /// add all content of buffer
+ ///
+ while (Size--) {
+ Sum = (UINT8) (Sum + (*Ptr++));
+ }
+ ///
+ /// set checksum
+ ///
+ Ptr = Buffer;
+ Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf
new file mode 100644
index 0000000000..0b24bbe71e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf
@@ -0,0 +1,47 @@
+## @file
+# Provides services to update ASL tables.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeAslUpdateLib
+FILE_GUID = 8621697D-4E3A-4bf2-ADB0-3E2FF06559CA
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = AslUpdateLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PcdLib
+BaseMemoryLib
+UefiLib
+MemoryAllocationLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeAslUpdateLib.c
+
+
+[Protocols]
+gEfiAcpiTableProtocolGuid ## CONSUMES
+gEfiAcpiSdtProtocolGuid ## CONSUMES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.c b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.c
new file mode 100644
index 0000000000..834315d236
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.c
@@ -0,0 +1,131 @@
+/** @file
+ Boot service DXE ASL update library implementation.
+
+ These functions in this file can be called during DXE and cannot be called during runtime
+ or in SMM which should use a RT or SMM library.
+
+ This library uses the ACPI Support protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Library/AslUpdateLib.h>
+
+//
+// Function implemenations
+//
+
+/**
+ Initialize the ASL update library state.
+ This must be called prior to invoking other library functions.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+InitializeAslUpdateLib (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will update immediate value assigned to a Name
+
+ @param[in] AslSignature - The signature of Operation Region that we want to update.
+ @param[in] Buffer - source of data to be written over original aml
+ @param[in] Length - length of data to be overwritten
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+UpdateNameAslCode (
+ IN UINT32 AslSignature,
+ IN VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function uses the ACPI SDT protocol to locate an ACPI table.
+ It is really only useful for finding tables that only have a single instance,
+ e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc.
+
+ @param[in] Signature - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in, out] Table - Updated with a pointer to the table
+ @param[in, out] Handle - AcpiSupport protocol table handle for the table found
+ @param[in, out] Version - The version of the table desired
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableBySignature (
+ IN UINT32 Signature,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This function uses the ACPI SDT protocol to locate an ACPI SSDT table.
+
+ @param[in] TableId - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in] TableIdSize - Length of the TableId to match. Table ID are 8 bytes long, this function
+ will consider it a match if the first TableIdSize bytes match
+ @param[in, out] Table - Updated with a pointer to the table
+ @param[in, out] Handle - AcpiSupport protocol table handle for the table found
+ @param[in, out] Version - See AcpiSupport protocol, GetAcpiTable function for use
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableByOemTableId (
+ IN UINT8 *TableId,
+ IN UINT8 TableIdSize,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param[in] Buffer Pointer to buffer to checksum
+ @param[in] Size Number of bytes to checksum
+ @param[in] ChecksumOffset Offset to place the checksum result in
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+AcpiChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.inf
new file mode 100644
index 0000000000..3805dbf1dd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.inf
@@ -0,0 +1,37 @@
+## @file
+# Provides services to update ASL tables.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeAslUpdateLibNull
+FILE_GUID = C7A3725F-6146-4FAB-B2EF-B4CED222DA52
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = AslUpdateLib
+
+
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeAslUpdateLibNull.c
+
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c
new file mode 100644
index 0000000000..3688872019
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c
@@ -0,0 +1,37 @@
+/** @file
+ This file contains routines that get PCI Express Address
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ This procedure will get PCIE address
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+
+ @retval PCIE address
+**/
+UINTN
+MmPciBase (
+ IN UINT32 Bus,
+ IN UINT32 Device,
+ IN UINT32 Function
+ )
+{
+ ASSERT ((Bus <= 0xFF) && (Device <= 0x1F) && (Function <= 0x7));
+
+ return ((UINTN) PcdGet64 (PcdPciExpressBaseAddress) + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
new file mode 100644
index 0000000000..24cae56d04
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
@@ -0,0 +1,47 @@
+## @file
+# Component description file for the PeiDxeSmmMmPciLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmMmPciLib
+FILE_GUID = D03D6670-A032-11E2-9E96-0800200C9A66
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = MmPciLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+BaseLib
+PcdLib
+DebugLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+
+[Sources]
+PeiDxeSmmMmPciLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspCpuPolicyInitLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspCpuPolicyInitLib.c
new file mode 100644
index 0000000000..282f774831
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspCpuPolicyInitLib.c
@@ -0,0 +1,366 @@
+/** @file
+ Implementation of Fsp PCH Policy Initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PeiFspPolicyInitLib.h>
+
+#include <Ppi/SiPolicy.h>
+
+#include <CpuAccess.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <FspEas.h>
+
+/**
+ Performs FSP CPU PEI Policy initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspCpuPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ )
+{
+ EFI_STATUS Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
+ CPU_OVERCLOCKING_PREMEM_CONFIG *CpuOverClockingPreMemConfig;
+ CPU_CONFIG_LIB_PREMEM_CONFIG *CpuConfigLibPreMemConfig;
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Update SiCpuPolicy Pre-Mem Start\n"));
+
+ //
+ // Locate SiPreMemPolicyPpi
+ //
+ SiPreMemPolicyPpi = NULL;
+ Status = PeiServicesLocatePpi (
+ &gSiPreMemPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPreMemPolicyPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuOverclockingPreMemConfigGuid, (VOID *) &CpuOverClockingPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuConfigLibPreMemConfigGuid, (VOID *) &CpuConfigLibPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ ///Test RC Policies
+ ///
+
+ ///
+ ///
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Update SiCpuPolicy Pre-Mem End\n"));
+
+ //
+ // Overclocking PreMem policies
+ //
+ FspmUpd->FspmConfig.OcSupport = (UINT8) CpuOverClockingPreMemConfig->OcSupport;
+ FspmUpd->FspmConfig.OcLock = (UINT8) CpuOverClockingPreMemConfig->OcLock;
+ FspmUpd->FspmConfig.CoreMaxOcRatio = (UINT8) CpuOverClockingPreMemConfig->CoreMaxOcRatio;
+ FspmUpd->FspmConfig.CoreVoltageMode = (UINT8) CpuOverClockingPreMemConfig->CoreVoltageMode;
+ FspmUpd->FspmConfig.RingMinOcRatio = (UINT8) CpuOverClockingPreMemConfig->RingMinOcRatio;
+ FspmUpd->FspmConfig.RingMaxOcRatio = (UINT8) CpuOverClockingPreMemConfig->RingMaxOcRatio;
+ FspmUpd->FspmConfig.CoreVoltageOverride = (UINT16) CpuOverClockingPreMemConfig->CoreVoltageOverride;
+ FspmUpd->FspmConfig.CoreVoltageAdaptive = (UINT16) CpuOverClockingPreMemConfig->CoreVoltageAdaptive;
+ FspmUpd->FspmConfig.CoreVoltageOffset = (UINT16) CpuOverClockingPreMemConfig->CoreVoltageOffset;
+ FspmUpd->FspmConfig.CorePllVoltageOffset = (UINT8) CpuOverClockingPreMemConfig->CorePllVoltageOffset;
+ FspmUpd->FspmConfig.GtPllVoltageOffset = (UINT8) CpuOverClockingPreMemConfig->GtPllVoltageOffset;
+ FspmUpd->FspmConfig.RingPllVoltageOffset = (UINT8) CpuOverClockingPreMemConfig->RingPllVoltageOffset;
+ FspmUpd->FspmConfig.SaPllVoltageOffset = (UINT8) CpuOverClockingPreMemConfig->SaPllVoltageOffset;
+ FspmUpd->FspmConfig.McPllVoltageOffset = (UINT8) CpuOverClockingPreMemConfig->McPllVoltageOffset;
+ FspmUpd->FspmConfig.Avx2RatioOffset = (UINT8) CpuOverClockingPreMemConfig->Avx2RatioOffset;
+ FspmUpd->FspmConfig.BclkAdaptiveVoltage = (UINT8) CpuOverClockingPreMemConfig->BclkAdaptiveVoltage;
+
+ //
+ // Cpu Config Lib policies
+ //
+ FspmUpd->FspmConfig.HyperThreading = (UINT8) CpuConfigLibPreMemConfig->HyperThreading;
+ FspmUpd->FspmConfig.BootFrequency = (UINT8) CpuConfigLibPreMemConfig->BootFrequency;
+ FspmUpd->FspmConfig.ActiveCoreCount = (UINT8) CpuConfigLibPreMemConfig->ActiveCoreCount;
+ FspmUpd->FspmConfig.JtagC10PowerGateDisable = (UINT8) CpuConfigLibPreMemConfig->JtagC10PowerGateDisable;
+ FspmUpd->FspmConfig.FClkFrequency = (UINT8) CpuConfigLibPreMemConfig->FClkFrequency;
+ FspmUpd->FspmConfig.BistOnReset = (UINT8) CpuConfigLibPreMemConfig->BistOnReset;
+ FspmUpd->FspmConfig.VmxEnable = (UINT8) CpuConfigLibPreMemConfig->VmxEnable;
+ FspmUpd->FspmConfig.CpuRatioOverride = (UINT8) CpuConfigLibPreMemConfig->CpuRatioOverride;
+ FspmUpd->FspmConfig.CpuRatio = (UINT8) CpuConfigLibPreMemConfig->CpuRatio;
+ FspmUpd->FspmConfig.PeciSxReset = (UINT8) CpuConfigLibPreMemConfig->PeciSxReset;
+ FspmUpd->FspmConfig.PeciC10Reset = (UINT8) CpuConfigLibPreMemConfig->PeciC10Reset;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine is used to search SMRAM and get SmramCpuData point.
+
+ @retval SmramCpuData - The pointer of CPU information in SMRAM.
+ @retval NULL - Unable to find the CPU information.
+ **/
+
+STATIC
+SMRAM_CPU_DATA *
+GetSmmCpuData(
+ VOID
+ )
+{
+ UINT32 Address;
+ SMRAM_CPU_DATA *SmramCpuData;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_STATUS Status;
+ UINT32 TsegBase = 0;
+ UINT32 TsegSize = 0;
+
+ //
+ // Find TSEG Base using Fsp Resource Descriptor
+ //
+
+ Status = PeiServicesGetHobList ((VOID **) &Hob.Raw);
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)
+ && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
+ && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)
+ && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobTsegGuid))) {
+
+ TsegBase = (UINT32)Hob.ResourceDescriptor->PhysicalStart;
+ TsegSize = (UINT32)Hob.ResourceDescriptor->ResourceLength;
+ DEBUG((DEBUG_INFO, "Found gFspReservedMemoryResourceHobTsegGuid\n"));
+ break;
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+
+ ///
+ /// Search SMRAM on page alignment for the SMMNVS signature
+ ///
+ if(TsegBase && TsegSize ){
+ for (Address = (TsegBase + TsegSize - EFI_PAGE_SIZE); Address >= TsegBase; Address -= EFI_PAGE_SIZE ) {
+ SmramCpuData = (SMRAM_CPU_DATA *) (UINTN) Address;
+ if (CompareGuid(&SmramCpuData->HeaderGuid, &gSmramCpuDataHeaderGuid)) {
+ return SmramCpuData;
+ }
+ }
+ }
+
+ DEBUG((DEBUG_WARN, "SmramCpuData not found\n"));
+ return NULL;
+}
+
+/**
+ Performs FSP CPU PEI Policy post memory initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspCpuPolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ )
+{
+ EFI_STATUS Status;
+ SI_POLICY_PPI *SiPolicyPpi;
+ CPU_CONFIG *CpuConfig;
+ CPU_POWER_MGMT_BASIC_CONFIG *CpuPowerMgmtBasicConfig;
+ CPU_POWER_MGMT_CUSTOM_CONFIG *CpuPowerMgmtCustomConfig;
+ CPU_TEST_CONFIG *CpuTestConfig;
+ CPU_POWER_MGMT_TEST_CONFIG *CpuPowerMgmtTestConfig;
+ UINTN Index;
+ SMRAM_CPU_DATA *SmramCpuData;
+ UINT32 S3BspMtrrTablePointer;
+ UINT32 CpuS3ResumeDataPointer;
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Update SiCpuPolicy\n"));
+ //
+ // Locate gSiPolicyPpiGuid
+ //
+ SiPolicyPpi = NULL;
+ Status = PeiServicesLocatePpi (
+ &gSiPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPolicyPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuConfigGuid, (VOID *) &CpuConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtBasicConfigGuid, (VOID *) &CpuPowerMgmtBasicConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtCustomConfigGuid, (VOID *) &CpuPowerMgmtCustomConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuTestConfigGuid, (VOID *) &CpuTestConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtTestConfigGuid, (VOID *) &CpuPowerMgmtTestConfig);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Production RC Policies
+ //
+
+ CopyMem ((VOID *)&(FspsUpd->FspsConfig.CpuConfig), (VOID *)&(((CPU_CONFIG_UNION *)CpuConfig)->CpuConfigFsp.Data), sizeof (UINT32));
+ FspsUpd->FspsConfig.MicrocodePatchAddress = CpuConfig->MicrocodePatchAddress;
+
+ FspsUpd->FspsConfig.TurboMode = (UINT8) CpuPowerMgmtBasicConfig->TurboMode;
+
+ ///
+ ///Test RC Policies
+ ///
+ FspsUpd->FspsTestConfig.MlcStreamerPrefetcher = (UINT8) CpuTestConfig->MlcStreamerPrefetcher;
+ FspsUpd->FspsTestConfig.MlcSpatialPrefetcher = (UINT8) CpuTestConfig->MlcSpatialPrefetcher;
+ FspsUpd->FspsTestConfig.MonitorMwaitEnable = (UINT8) CpuTestConfig->MonitorMwaitEnable;
+ FspsUpd->FspsTestConfig.DebugInterfaceEnable = (UINT8) CpuTestConfig->DebugInterfaceEnable;
+ FspsUpd->FspsTestConfig.DebugInterfaceLockEnable = (UINT8) CpuTestConfig->DebugInterfaceLockEnable;
+ FspsUpd->FspsTestConfig.ApIdleManner = (UINT8) CpuTestConfig->ApIdleManner;
+ FspsUpd->FspsTestConfig.ApHandoffManner = (UINT8) CpuTestConfig->ApHandoffManner;
+ FspsUpd->FspsTestConfig.ProcTraceOutputScheme = (UINT8) CpuTestConfig->ProcTraceOutputScheme;
+ FspsUpd->FspsTestConfig.ProcTraceEnable = (UINT8) CpuTestConfig->ProcTraceEnable;
+ FspsUpd->FspsTestConfig.ProcTraceMemSize = (UINT8) CpuTestConfig->ProcTraceMemSize;
+ FspsUpd->FspsTestConfig.VoltageOptimization = (UINT8) CpuTestConfig->VoltageOptimization;
+
+
+ FspsUpd->FspsTestConfig.OneCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->OneCoreRatioLimit;
+ FspsUpd->FspsTestConfig.TwoCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->TwoCoreRatioLimit;
+ FspsUpd->FspsTestConfig.ThreeCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->ThreeCoreRatioLimit;
+ FspsUpd->FspsTestConfig.FourCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->FourCoreRatioLimit;
+ FspsUpd->FspsTestConfig.FiveCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->FiveCoreRatioLimit;
+ FspsUpd->FspsTestConfig.SixCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->SixCoreRatioLimit;
+ FspsUpd->FspsTestConfig.SevenCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->SevenCoreRatioLimit;
+ FspsUpd->FspsTestConfig.EightCoreRatioLimit = (UINT8) CpuPowerMgmtBasicConfig->EightCoreRatioLimit;
+ FspsUpd->FspsTestConfig.Hwp = (UINT8) CpuPowerMgmtBasicConfig->Hwp;
+ FspsUpd->FspsTestConfig.HdcControl = (UINT8) CpuPowerMgmtBasicConfig->HdcControl;
+ FspsUpd->FspsTestConfig.PowerLimit1Time = (UINT8) CpuPowerMgmtBasicConfig->PowerLimit1Time;
+ FspsUpd->FspsTestConfig.PowerLimit2 = (UINT8) CpuPowerMgmtBasicConfig->PowerLimit2;
+ FspsUpd->FspsTestConfig.TurboPowerLimitLock = (UINT8) CpuPowerMgmtBasicConfig->TurboPowerLimitLock;
+ FspsUpd->FspsTestConfig.PowerLimit3Time = (UINT8) CpuPowerMgmtBasicConfig->PowerLimit3Time;
+ FspsUpd->FspsTestConfig.PowerLimit3DutyCycle = (UINT8) CpuPowerMgmtBasicConfig->PowerLimit3DutyCycle;
+ FspsUpd->FspsTestConfig.PowerLimit3Lock = (UINT8) CpuPowerMgmtBasicConfig->PowerLimit3Lock;
+ FspsUpd->FspsTestConfig.PowerLimit4Lock = (UINT8) CpuPowerMgmtBasicConfig->PowerLimit4Lock;
+ FspsUpd->FspsTestConfig.TccActivationOffset = (UINT8) CpuPowerMgmtBasicConfig->TccActivationOffset;
+ FspsUpd->FspsTestConfig.TccOffsetClamp = (UINT8) CpuPowerMgmtBasicConfig->TccOffsetClamp;
+ FspsUpd->FspsTestConfig.TccOffsetLock = (UINT8) CpuPowerMgmtBasicConfig->TccOffsetLock;
+ FspsUpd->FspsTestConfig.PowerLimit1 = (UINT32) (CpuPowerMgmtBasicConfig->PowerLimit1 * 125);
+ FspsUpd->FspsTestConfig.PowerLimit2Power = (UINT32) (CpuPowerMgmtBasicConfig->PowerLimit2Power * 125);
+ FspsUpd->FspsTestConfig.PowerLimit3 = (UINT32) (CpuPowerMgmtBasicConfig->PowerLimit3 * 125);
+ FspsUpd->FspsTestConfig.PowerLimit4 = (UINT32) (CpuPowerMgmtBasicConfig->PowerLimit4 * 125);
+ FspsUpd->FspsTestConfig.TccOffsetTimeWindowForRatl = (UINT32) CpuPowerMgmtBasicConfig->TccOffsetTimeWindowForRatl;
+
+ FspsUpd->FspsTestConfig.NumberOfEntries = (UINT8) CpuPowerMgmtCustomConfig->CustomRatioTable.NumberOfEntries;
+ FspsUpd->FspsTestConfig.Custom1PowerLimit1Time = (UINT8) CpuPowerMgmtCustomConfig->CustomConfigTdpTable[0].CustomPowerLimit1Time;
+ FspsUpd->FspsTestConfig.Custom2PowerLimit1Time = (UINT8) CpuPowerMgmtCustomConfig->CustomConfigTdpTable[1].CustomPowerLimit1Time;
+ FspsUpd->FspsTestConfig.Custom3PowerLimit1Time = (UINT8) CpuPowerMgmtCustomConfig->CustomConfigTdpTable[2].CustomPowerLimit1Time;
+ FspsUpd->FspsTestConfig.Custom1TurboActivationRatio = (UINT8) CpuPowerMgmtCustomConfig->CustomConfigTdpTable[0].CustomTurboActivationRatio;
+ FspsUpd->FspsTestConfig.Custom2TurboActivationRatio = (UINT8) CpuPowerMgmtCustomConfig->CustomConfigTdpTable[1].CustomTurboActivationRatio;
+ FspsUpd->FspsTestConfig.Custom3TurboActivationRatio = (UINT8) CpuPowerMgmtCustomConfig->CustomConfigTdpTable[2].CustomTurboActivationRatio;
+ FspsUpd->FspsTestConfig.ConfigTdpLock = (UINT8) CpuPowerMgmtCustomConfig->ConfigTdpLock;
+ FspsUpd->FspsTestConfig.ConfigTdpBios = (UINT8) CpuPowerMgmtCustomConfig->ConfigTdpBios;
+ FspsUpd->FspsTestConfig.MaxRatio = (UINT16) CpuPowerMgmtCustomConfig->CustomRatioTable.MaxRatio;
+ for (Index = 0; Index < CpuPowerMgmtCustomConfig->CustomRatioTable.NumberOfEntries; Index++) {
+ FspsUpd->FspsTestConfig.StateRatio[Index] = (UINT16) CpuPowerMgmtCustomConfig->CustomRatioTable.StateRatio[Index];
+ }
+ FspsUpd->FspsTestConfig.Custom1PowerLimit1 = (UINT32) (CpuPowerMgmtCustomConfig->CustomConfigTdpTable[0].CustomPowerLimit1 * 125);
+ FspsUpd->FspsTestConfig.Custom1PowerLimit2 = (UINT32) (CpuPowerMgmtCustomConfig->CustomConfigTdpTable[0].CustomPowerLimit2 * 125);
+ FspsUpd->FspsTestConfig.Custom2PowerLimit1 = (UINT32) (CpuPowerMgmtCustomConfig->CustomConfigTdpTable[1].CustomPowerLimit1 * 125);
+ FspsUpd->FspsTestConfig.Custom2PowerLimit2 = (UINT32) (CpuPowerMgmtCustomConfig->CustomConfigTdpTable[1].CustomPowerLimit2 * 125);
+ FspsUpd->FspsTestConfig.Custom3PowerLimit1 = (UINT32) (CpuPowerMgmtCustomConfig->CustomConfigTdpTable[2].CustomPowerLimit1 * 125);
+ FspsUpd->FspsTestConfig.Custom3PowerLimit2 = (UINT32) (CpuPowerMgmtCustomConfig->CustomConfigTdpTable[2].CustomPowerLimit2 * 125);
+
+ FspsUpd->FspsTestConfig.Eist = (UINT8) CpuPowerMgmtTestConfig->Eist;
+ FspsUpd->FspsTestConfig.EnergyEfficientPState = (UINT8) CpuPowerMgmtTestConfig->EnergyEfficientPState;
+ FspsUpd->FspsTestConfig.EnergyEfficientTurbo = (UINT8) CpuPowerMgmtTestConfig->EnergyEfficientTurbo;
+ FspsUpd->FspsTestConfig.TStates = (UINT8) CpuPowerMgmtTestConfig->TStates;
+ FspsUpd->FspsTestConfig.BiProcHot = (UINT8) CpuPowerMgmtTestConfig->BiProcHot;
+ FspsUpd->FspsTestConfig.DisableProcHotOut = (UINT8) CpuPowerMgmtTestConfig->DisableProcHotOut;
+ FspsUpd->FspsTestConfig.ProcHotResponse = (UINT8) CpuPowerMgmtTestConfig->ProcHotResponse;
+ FspsUpd->FspsTestConfig.DisableVrThermalAlert = (UINT8) CpuPowerMgmtTestConfig->DisableVrThermalAlert;
+ FspsUpd->FspsTestConfig.AutoThermalReporting = (UINT8) CpuPowerMgmtTestConfig->AutoThermalReporting;
+ FspsUpd->FspsTestConfig.ThermalMonitor = (UINT8) CpuPowerMgmtTestConfig->ThermalMonitor;
+ FspsUpd->FspsTestConfig.Cx = (UINT8) CpuPowerMgmtTestConfig->Cx;
+ FspsUpd->FspsTestConfig.PmgCstCfgCtrlLock = (UINT8) CpuPowerMgmtTestConfig->PmgCstCfgCtrlLock;
+ FspsUpd->FspsTestConfig.C1e = (UINT8) CpuPowerMgmtTestConfig->C1e;
+ FspsUpd->FspsTestConfig.PkgCStateDemotion = (UINT8) CpuPowerMgmtTestConfig->PkgCStateDemotion;
+ FspsUpd->FspsTestConfig.PkgCStateUnDemotion = (UINT8) CpuPowerMgmtTestConfig->PkgCStateUnDemotion;
+ FspsUpd->FspsTestConfig.CStatePreWake = (UINT8) CpuPowerMgmtTestConfig->CStatePreWake;
+ FspsUpd->FspsTestConfig.TimedMwait = (UINT8) CpuPowerMgmtTestConfig->TimedMwait;
+ FspsUpd->FspsTestConfig.CstCfgCtrIoMwaitRedirection = (UINT8) CpuPowerMgmtTestConfig->CstCfgCtrIoMwaitRedirection;
+ FspsUpd->FspsTestConfig.PkgCStateLimit = (UINT8) CpuPowerMgmtTestConfig->PkgCStateLimit;
+ FspsUpd->FspsTestConfig.CstateLatencyControl0TimeUnit = (UINT8) CpuPowerMgmtTestConfig->CstateLatencyControl0TimeUnit;
+ FspsUpd->FspsTestConfig.CstateLatencyControl1TimeUnit = (UINT8) CpuPowerMgmtTestConfig->CstateLatencyControl1TimeUnit;
+ FspsUpd->FspsTestConfig.CstateLatencyControl2TimeUnit = (UINT8) CpuPowerMgmtTestConfig->CstateLatencyControl2TimeUnit;
+ FspsUpd->FspsTestConfig.CstateLatencyControl3TimeUnit = (UINT8) CpuPowerMgmtTestConfig->CstateLatencyControl3TimeUnit;
+ FspsUpd->FspsTestConfig.CstateLatencyControl4TimeUnit = (UINT8) CpuPowerMgmtTestConfig->CstateLatencyControl4TimeUnit;
+ FspsUpd->FspsTestConfig.CstateLatencyControl5TimeUnit = (UINT8) CpuPowerMgmtTestConfig->CstateLatencyControl5TimeUnit;
+ FspsUpd->FspsTestConfig.PpmIrmSetting = (UINT8) CpuPowerMgmtTestConfig->PpmIrmSetting;
+ FspsUpd->FspsTestConfig.ProcHotLock = (UINT8) CpuPowerMgmtTestConfig->ProcHotLock;
+ FspsUpd->FspsTestConfig.RaceToHalt = (UINT8) CpuPowerMgmtTestConfig->RaceToHalt;
+ FspsUpd->FspsTestConfig.ConfigTdpLevel = (UINT8) CpuPowerMgmtTestConfig->ConfigTdpLevel;
+ FspsUpd->FspsTestConfig.CstateLatencyControl0Irtl = (UINT16) CpuPowerMgmtTestConfig->CstateLatencyControl0Irtl;
+ FspsUpd->FspsTestConfig.CstateLatencyControl1Irtl = (UINT16) CpuPowerMgmtTestConfig->CstateLatencyControl1Irtl;
+ FspsUpd->FspsTestConfig.CstateLatencyControl2Irtl = (UINT16) CpuPowerMgmtTestConfig->CstateLatencyControl2Irtl;
+ FspsUpd->FspsTestConfig.CstateLatencyControl3Irtl = (UINT16) CpuPowerMgmtTestConfig->CstateLatencyControl3Irtl;
+ FspsUpd->FspsTestConfig.CstateLatencyControl4Irtl = (UINT16) CpuPowerMgmtTestConfig->CstateLatencyControl4Irtl;
+ FspsUpd->FspsTestConfig.CstateLatencyControl5Irtl = (UINT16) CpuPowerMgmtTestConfig->CstateLatencyControl5Irtl;
+
+ Status = PeiServicesGetBootMode(&BootMode);
+ if ((Status == EFI_SUCCESS) && (BootMode == BOOT_ON_S3_RESUME)) {
+ SmramCpuData = GetSmmCpuData();
+ if (SmramCpuData != NULL) {
+ S3BspMtrrTablePointer = (UINT32) AllocateZeroPool(SmramCpuData->S3BspMtrrTableSize); //Add Null terminator
+ FspsUpd->FspsConfig.CpuS3ResumeMtrrData = S3BspMtrrTablePointer;
+ FspsUpd->FspsConfig.CpuS3ResumeMtrrDataSize = (UINT16) SmramCpuData->S3BspMtrrTableSize;
+ //
+ // Copy BSP MTRR table to UPD.
+ //
+ CopyMem((VOID*) S3BspMtrrTablePointer,
+ (UINT8 *) SmramCpuData + SmramCpuData->S3BspMtrrTableOffset,
+ SmramCpuData->S3BspMtrrTableSize);
+
+ CpuS3ResumeDataPointer = (UINT32) AllocateZeroPool(SmramCpuData->CpuPrivateDataSize);
+ FspsUpd->FspsTestConfig.CpuS3ResumeData = CpuS3ResumeDataPointer;
+ FspsUpd->FspsTestConfig.CpuS3ResumeDataSize = (UINT16) SmramCpuData->CpuPrivateDataSize;
+ //
+ // Copy CPU_PRIVATE_DATA to UPD.
+ //
+ CopyMem((VOID*) CpuS3ResumeDataPointer,
+ (UINT8 *) SmramCpuData + SmramCpuData->CpuPrivateDataOffset,
+ SmramCpuData->CpuPrivateDataSize);
+ } else {
+ //@todo Check if an assert can be handled cleanly
+ DEBUG((DEBUG_WARN, "Unable to initialize S3 data\n"));
+ }
+
+ }
+ ///
+ ///
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMePolicyInitLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMePolicyInitLib.c
new file mode 100644
index 0000000000..d97bf8be57
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMePolicyInitLib.c
@@ -0,0 +1,129 @@
+/** @file
+ Implementation of Fsp Me Policy Initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PeiFspPolicyInitLib.h>
+
+#include <Ppi/SiPolicy.h>
+
+/**
+ Performs FSP ME PEI Policy pre mem initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspMePolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ )
+{
+ EFI_STATUS Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicy;
+ ME_PEI_PREMEM_CONFIG *MePeiPreMemConfig;
+
+ DEBUG ((DEBUG_INFO, "PeiFspMePolicyInitPreMem\n"));
+
+ //
+ // Locate gSiPreMemPolicyPpi
+ //
+ SiPreMemPolicy = NULL;
+ Status = PeiServicesLocatePpi (
+ &gSiPreMemPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPreMemPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gMePeiPreMemConfigGuid, (VOID *) &MePeiPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ FspmUpd->FspmConfig.HeciTimeouts = (UINT8) MePeiPreMemConfig->HeciTimeouts;
+
+ //
+ // Test policies
+ //
+ FspmUpd->FspmTestConfig.DidInitStat = (UINT8) MePeiPreMemConfig->DidInitStat;
+ FspmUpd->FspmTestConfig.DisableCpuReplacedPolling = (UINT8) MePeiPreMemConfig->DisableCpuReplacedPolling;
+ FspmUpd->FspmTestConfig.SendDidMsg = (UINT8) MePeiPreMemConfig->SendDidMsg;
+ FspmUpd->FspmTestConfig.DisableHeciRetry = (UINT8) MePeiPreMemConfig->DisableHeciRetry;
+ FspmUpd->FspmTestConfig.DisableMessageCheck = (UINT8) MePeiPreMemConfig->DisableMessageCheck;
+ FspmUpd->FspmTestConfig.SkipMbpHob = (UINT8) MePeiPreMemConfig->SkipMbpHob;
+
+ FspmUpd->FspmTestConfig.HeciCommunication2 = (UINT8) MePeiPreMemConfig->HeciCommunication2;
+ FspmUpd->FspmTestConfig.KtDeviceEnable = (UINT8) MePeiPreMemConfig->KtDeviceEnable;
+ FspmUpd->FspmTestConfig.IderDeviceEnable = (UINT8) MePeiPreMemConfig->IderDeviceEnable;
+
+
+ FspmUpd->FspmConfig.Heci1BarAddress = MePeiPreMemConfig->Heci1BarAddress;
+ FspmUpd->FspmConfig.Heci2BarAddress = MePeiPreMemConfig->Heci2BarAddress;
+ FspmUpd->FspmConfig.Heci3BarAddress = MePeiPreMemConfig->Heci3BarAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Performs FSP ME PEI Policy initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspMePolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ )
+{
+ EFI_STATUS Status;
+ SI_POLICY_PPI *SiPolicyPpi;
+ ME_PEI_CONFIG *MePeiConfig;
+
+ DEBUG ((DEBUG_INFO, "PeiFspMePolicyInit \n"));
+ //
+ // Locate gSiPolicyPpiGuid
+ //
+ SiPolicyPpi = NULL;
+ Status = PeiServicesLocatePpi (
+ &gSiPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPolicyPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gMePeiConfigGuid, (VOID *) &MePeiConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ FspsUpd->FspsConfig.Heci3Enabled = (UINT8) MePeiConfig->Heci3Enabled;
+ FspsUpd->FspsConfig.MeUnconfigOnRtcClear = (UINT8) MePeiConfig->MeUnconfigOnRtcClear;
+ FspsUpd->FspsConfig.MeUnconfigIsValid = (UINT8) MePeiConfig->MeUnconfigIsValid;
+
+ //
+ // Test policies
+ //
+ FspsUpd->FspsTestConfig.EndOfPostMessage = (UINT8) MePeiConfig->EndOfPostMessage;
+ FspsUpd->FspsTestConfig.DisableD0I3SettingForHeci = (UINT8) MePeiConfig->DisableD0I3SettingForHeci;
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMiscUpdInitLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMiscUpdInitLib.c
new file mode 100644
index 0000000000..b9329e4c8a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspMiscUpdInitLib.c
@@ -0,0 +1,56 @@
+/** @file
+ Implementation of Fsp Misc UPD Initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PeiFspPolicyInitLib.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Library/DebugLib.h>
+#include <Library/DebugPrintErrorLevelLib.h>
+
+/**
+ Performs FSP Misc UPD initialization.
+
+ @param[in][out] FspmUpd Pointer to FSPM_UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspMiscUpdInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Locate system configuration variable
+ //
+ FspmUpd->FspmArchUpd.StackBase = (VOID *)(UINTN)(PcdGet32(PcdTemporaryRamBase) + PcdGet32(PcdTemporaryRamSize) - (PcdGet32(PcdFspTemporaryRamSize) + PcdGet32(PcdFspReservedBufferSize)));
+ FspmUpd->FspmArchUpd.StackSize = PcdGet32(PcdFspTemporaryRamSize);
+
+ Status = PeiServicesGetBootMode (&(FspmUpd->FspmArchUpd.BootMode));
+ if (EFI_ERROR (Status)) {
+ FspmUpd->FspmArchUpd.BootMode = BOOT_WITH_FULL_CONFIGURATION;
+ }
+
+ FspmUpd->FspmArchUpd.BootLoaderTolumSize = 0x0;
+
+ //
+ // Initialize S3 Data variable (S3DataPtr). It may be used for warm and fast boot paths.
+ //
+ FspmUpd->FspmArchUpd.NvsBufferPtr = NULL;
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPchPolicyInitLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPchPolicyInitLib.c
new file mode 100644
index 0000000000..3f7e297c0b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPchPolicyInitLib.c
@@ -0,0 +1,713 @@
+/** @file
+ Implementation of Fsp PCH Policy Initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PeiFspPolicyInitLib.h>
+
+#include <Ppi/SiPolicy.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+
+/**
+ Performs FSP PCH PEI Policy pre mem initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspPchPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicy;
+ PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig;
+ PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig;
+ PCH_DCI_PREMEM_CONFIG *DciPreMemConfig;
+ PCH_HPET_PREMEM_CONFIG *HpetPreMemConfig;
+ PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
+ PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
+ PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig;
+ PCH_HSIO_PREMEM_CONFIG *HsioPreMemConfig;
+ PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig;
+ PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
+ PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP UpdatePeiPchPolicyPreMem\n"));
+ //
+ // Locate PchPreMemPolicyPpi
+ //
+ SiPreMemPolicy = NULL;
+ Status = PeiServicesLocatePpi (
+ &gSiPreMemPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPreMemPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gTraceHubPreMemConfigGuid, (VOID *) &TraceHubPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gSmbusPreMemConfigGuid, (VOID *) &SmbusPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gDciPreMemConfigGuid, (VOID *) &DciPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHpetPreMemConfigGuid, (VOID *) &HpetPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioPciePreMemConfigGuid, (VOID *) &HsioPciePreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioSataPreMemConfigGuid, (VOID *) &HsioSataPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioPreMemConfigGuid, (VOID *) &HsioPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gLpcPreMemConfigGuid, (VOID *) &LpcPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gPchGeneralPreMemConfigGuid, (VOID *) &PchGeneralPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gWatchDogPreMemConfigGuid, (VOID *) &WdtPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gPcieRpPreMemConfigGuid, (VOID *) &PcieRpPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Update PCIE RP policies
+ //
+ FspmUpd->FspmConfig.PcieRpEnableMask = PcieRpPreMemConfig->RpEnabledMask & ((1 << KBL_PCH_H_PCIE_MAX_ROOT_PORTS) - 1);
+
+ //
+ // Update TraceHub policies
+ //
+ FspmUpd->FspmConfig.EnableTraceHub = ((UINT8)TraceHubPreMemConfig->EnableMode == 0) ? 0 : 1;
+ FspmUpd->FspmConfig.TraceHubMemReg0Size = (UINT32)TraceHubPreMemConfig->MemReg0Size;
+ FspmUpd->FspmConfig.TraceHubMemReg1Size = (UINT32)TraceHubPreMemConfig->MemReg1Size;
+
+ //
+ // Update Smbus policies
+ //
+ FspmUpd->FspmConfig.SmbusEnable = (UINT8)SmbusPreMemConfig->Enable;
+ FspmUpd->FspmConfig.SmbusArpEnable = (UINT8)SmbusPreMemConfig->ArpEnable;
+ FspmUpd->FspmTestConfig.SmbusDynamicPowerGating = (UINT8)SmbusPreMemConfig->DynamicPowerGating;
+ FspmUpd->FspmTestConfig.SmbusSpdWriteDisable = (UINT8)SmbusPreMemConfig->SpdWriteDisable;
+ FspmUpd->FspmConfig.PchSmbusIoBase = (UINT16)SmbusPreMemConfig->SmbusIoBase;
+ FspmUpd->FspmConfig.PchNumRsvdSmbusAddresses = (UINT8)SmbusPreMemConfig->NumRsvdSmbusAddresses;
+ FspmUpd->FspmConfig.RsvdSmbusAddressTablePtr = (UINT32)SmbusPreMemConfig->RsvdSmbusAddressTable;
+
+ //
+ // Update Dci policies
+ //
+ FspmUpd->FspmTestConfig.PchDciEn = (UINT8)DciPreMemConfig->DciEn;
+
+ //
+ // Update HPET policies
+ //
+ FspmUpd->FspmConfig.PchHpetEnable = (UINT8)HpetPreMemConfig->Enable;
+ FspmUpd->FspmConfig.PchHpetBdfValid = (UINT8)HpetPreMemConfig->BdfValid;
+ FspmUpd->FspmConfig.PchHpetBusNumber = (UINT8)HpetPreMemConfig->BusNumber;
+ FspmUpd->FspmConfig.PchHpetDeviceNumber = (UINT8)HpetPreMemConfig->DeviceNumber;
+ FspmUpd->FspmConfig.PchHpetFunctionNumber = (UINT8)HpetPreMemConfig->FunctionNumber;
+ FspmUpd->FspmConfig.PchHpetBase = (UINT32)HpetPreMemConfig->Base;
+
+ //
+ // Update HSIO PCIE policies
+ //
+ FspmUpd->FspmConfig.PchPmPciePllSsc = (UINT8)HsioPciePreMemConfig->PciePllSsc;
+ for (Index = 0; Index < KBL_PCH_H_PCIE_MAX_ROOT_PORTS; Index ++) {
+ FspmUpd->FspmConfig.PchPcieHsioRxSetCtleEnable[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioRxSetCtleEnable;
+ FspmUpd->FspmConfig.PchPcieHsioRxSetCtle[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioRxSetCtle;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen1DownscaleAmpEnable[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmpEnable;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen1DownscaleAmp[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmp;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen2DownscaleAmpEnable[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmpEnable;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen2DownscaleAmp[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmp;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen3DownscaleAmpEnable[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmpEnable;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen3DownscaleAmp[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmp;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen1DeEmphEnable[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmphEnable;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen1DeEmph[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmph;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen2DeEmph3p5Enable[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5Enable;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen2DeEmph3p5[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen2DeEmph6p0Enable[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0Enable;
+ FspmUpd->FspmConfig.PchPcieHsioTxGen2DeEmph6p0[Index] = (UINT8)HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0;
+ }
+
+ //
+ // Update HSIO SATA policies
+ //
+ for (Index = 0; Index < PCH_MAX_SATA_PORTS; Index ++) {
+ FspmUpd->FspmConfig.PchSataHsioRxGen1EqBoostMagEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMagEnable;
+ FspmUpd->FspmConfig.PchSataHsioRxGen1EqBoostMag[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMag;
+ FspmUpd->FspmConfig.PchSataHsioRxGen2EqBoostMagEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMagEnable;
+ FspmUpd->FspmConfig.PchSataHsioRxGen2EqBoostMag[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMag;
+ FspmUpd->FspmConfig.PchSataHsioRxGen3EqBoostMagEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMagEnable;
+ FspmUpd->FspmConfig.PchSataHsioRxGen3EqBoostMag[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMag;
+ FspmUpd->FspmConfig.PchSataHsioTxGen1DownscaleAmpEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmpEnable;
+ FspmUpd->FspmConfig.PchSataHsioTxGen1DownscaleAmp[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmp;
+ FspmUpd->FspmConfig.PchSataHsioTxGen2DownscaleAmpEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmpEnable;
+ FspmUpd->FspmConfig.PchSataHsioTxGen2DownscaleAmp[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmp;
+ FspmUpd->FspmConfig.PchSataHsioTxGen3DownscaleAmpEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmpEnable;
+ FspmUpd->FspmConfig.PchSataHsioTxGen3DownscaleAmp[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmp;
+ FspmUpd->FspmConfig.PchSataHsioTxGen1DeEmphEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmphEnable;
+ FspmUpd->FspmConfig.PchSataHsioTxGen1DeEmph[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmph;
+ FspmUpd->FspmConfig.PchSataHsioTxGen2DeEmphEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmphEnable;
+ FspmUpd->FspmConfig.PchSataHsioTxGen2DeEmph[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmph;
+ FspmUpd->FspmConfig.PchSataHsioTxGen3DeEmphEnable[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmphEnable;
+ FspmUpd->FspmConfig.PchSataHsioTxGen3DeEmph[Index] = (UINT8)HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmph;
+ }
+
+ //
+ // Update HSIO policies
+ //
+ FspmUpd->FspmTestConfig.ChipsetInitMessage = (UINT8)HsioPreMemConfig->ChipsetInitMessage;
+ FspmUpd->FspmTestConfig.BypassPhySyncReset = (UINT8)HsioPreMemConfig->BypassPhySyncReset;
+
+ //
+ // Update LPC policies
+ //
+ FspmUpd->FspmConfig.PchLpcEnhancePort8xhDecoding = (UINT8)LpcPreMemConfig->EnhancePort8xhDecoding;
+
+ //
+ // Update Pch General Premem policies
+ //
+ FspmUpd->FspmConfig.PchAcpiBase = (UINT16)PchGeneralPreMemConfig->AcpiBase;
+ FspmUpd->FspmConfig.PchPort80Route = (UINT8)PchGeneralPreMemConfig->Port80Route;
+
+ //
+ // Update Wdt policies
+ //
+ FspmUpd->FspmTestConfig.WdtDisableAndLock = (UINT8)WdtPreMemConfig->DisableAndLock;
+
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Performs FSP PCH PEI Policy initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspPchPolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ SI_POLICY_PPI *SiPolicy;
+ PCH_LAN_CONFIG *LanConfig;
+ PCH_HDAUDIO_CONFIG *HdAudioConfig;
+ PCH_SCS_CONFIG *ScsConfig;
+ PCH_ISH_CONFIG *IshConfig;
+ PCH_SPI_CONFIG *SpiConfig;
+ PCH_SATA_CONFIG *SataConfig;
+ PCH_USB_CONFIG *UsbConfig;
+ PCH_SERIAL_IO_CONFIG *SerialIoConfig;
+ PCH_INTERRUPT_CONFIG *InterruptConfig;
+ PCH_LOCK_DOWN_CONFIG *LockDownConfig;
+ PCH_CIO2_CONFIG *Cio2Config;
+ PCH_PCIE_CONFIG *PcieRpConfig;
+ PCH_DMI_CONFIG *DmiConfig;
+ PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
+ PCH_IOAPIC_CONFIG *IoApicConfig;
+ PCH_P2SB_CONFIG *P2sbConfig;
+ PCH_GENERAL_CONFIG *PchGeneralConfig;
+ PCH_PM_CONFIG *PmConfig;
+ PCH_PORT61H_SMM_CONFIG *Port61hConfig;
+ PCH_LPC_SIRQ_CONFIG *PchSerialIrqConfig;
+ PCH_THERMAL_CONFIG *PchThermalConfig;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP UpdatePeiPchPolicy\n"));
+ //
+ // Locate SiPolicyPpi
+ //
+ SiPolicy = NULL;
+ Status = PeiServicesLocatePpi (
+ &gSiPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gLanConfigGuid, (VOID *) &LanConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gHdAudioConfigGuid, (VOID *) &HdAudioConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gScsConfigGuid, (VOID *) &ScsConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gIshConfigGuid, (VOID *) &IshConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gSpiConfigGuid, (VOID *) &SpiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gSataConfigGuid, (VOID *) &SataConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gUsbConfigGuid, (VOID *) &UsbConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gSerialIoConfigGuid, (VOID *) &SerialIoConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gInterruptConfigGuid, (VOID *) &InterruptConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gCio2ConfigGuid, (VOID *) &Cio2Config);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gDmiConfigGuid, (VOID *) &DmiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gFlashProtectionConfigGuid, (VOID *) &FlashProtectionConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gIoApicConfigGuid, (VOID *) &IoApicConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gP2sbConfigGuid, (VOID *) &P2sbConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPchGeneralConfigGuid, (VOID *) &PchGeneralConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPmConfigGuid, (VOID *) &PmConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPort61ConfigGuid, (VOID *) &Port61hConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gSerialIrqConfigGuid, (VOID *) &PchSerialIrqConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gThermalConfigGuid, (VOID *) &PchThermalConfig);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Update LAN policies
+ //
+ FspsUpd->FspsConfig.PchLanEnable = (UINT8)LanConfig->Enable;
+ FspsUpd->FspsConfig.PchLanLtrEnable = (UINT8)LanConfig->LtrEnable;
+ FspsUpd->FspsConfig.PchLanK1OffEnable = (UINT8)LanConfig->K1OffEnable;
+ FspsUpd->FspsConfig.PchLanClkReqSupported = (UINT8)LanConfig->ClkReqSupported;
+ FspsUpd->FspsConfig.PchLanClkReqNumber = (UINT8)LanConfig->ClkReqNumber;
+
+ //
+ // Update HDA policies
+ //
+ FspsUpd->FspsConfig.PchHdaEnable = (UINT8)HdAudioConfig->Enable;
+ FspsUpd->FspsConfig.PchHdaDspEnable = (UINT8)HdAudioConfig->DspEnable;
+ FspsUpd->FspsConfig.PchHdaIoBufferOwnership = (UINT8)HdAudioConfig->IoBufferOwnership;
+
+ FspsUpd->FspsConfig.PchHdaPme = (UINT8)HdAudioConfig->Pme;
+ FspsUpd->FspsConfig.PchHdaIoBufferVoltage = (UINT8)HdAudioConfig->IoBufferVoltage;
+ FspsUpd->FspsConfig.PchHdaVcType = (UINT8)HdAudioConfig->VcType;
+ FspsUpd->FspsConfig.PchHdaLinkFrequency = (UINT8)HdAudioConfig->HdAudioLinkFrequency;
+ FspsUpd->FspsConfig.PchHdaIDispLinkFrequency = (UINT8)HdAudioConfig->IDispLinkFrequency;
+ FspsUpd->FspsConfig.PchHdaIDispLinkTmode = (UINT8)HdAudioConfig->IDispLinkTmode;
+ FspsUpd->FspsConfig.PchHdaDspUaaCompliance = (UINT8)HdAudioConfig->DspUaaCompliance;
+ FspsUpd->FspsConfig.PchHdaIDispCodecDisconnect = (UINT8)HdAudioConfig->IDispCodecDisconnect;
+ FspsUpd->FspsConfig.PchHdaDspEndpointDmic = (UINT8)HdAudioConfig->DspEndpointDmic;
+ FspsUpd->FspsConfig.PchHdaDspEndpointBluetooth = (UINT8)HdAudioConfig->DspEndpointBluetooth;
+ FspsUpd->FspsConfig.PchHdaDspEndpointI2s = (UINT8)HdAudioConfig->DspEndpointI2s;
+ FspsUpd->FspsConfig.PchHdaDspFeatureMask = (UINT32)HdAudioConfig->DspFeatureMask;
+ FspsUpd->FspsTestConfig.PchHdaResetWaitTimer = (UINT16)HdAudioConfig->ResetWaitTimer;
+ FspsUpd->FspsConfig.PchHdaVerbTableEntryNum = HdAudioConfig->VerbTableEntryNum;
+ FspsUpd->FspsConfig.PchHdaVerbTablePtr = HdAudioConfig->VerbTablePtr;
+
+ //
+ // Update CIO2 policies
+ //
+ FspsUpd->FspsConfig.PchCio2Enable = (UINT8)Cio2Config->DeviceEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortATermOvrEnable = (UINT8)Cio2Config->SkyCamPortATermOvrEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortBTermOvrEnable = (UINT8)Cio2Config->SkyCamPortBTermOvrEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortCTermOvrEnable = (UINT8)Cio2Config->SkyCamPortCTermOvrEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortDTermOvrEnable = (UINT8)Cio2Config->SkyCamPortDTermOvrEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortATrimEnable = (UINT8)Cio2Config->PortATrimEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortBTrimEnable = (UINT8)Cio2Config->PortBTrimEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortCTrimEnable = (UINT8)Cio2Config->PortCTrimEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortDTrimEnable = (UINT8)Cio2Config->PortDTrimEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortACtleEnable = (UINT8)Cio2Config->PortACtleEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortBCtleEnable = (UINT8)Cio2Config->PortBCtleEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortCDCtleEnable = (UINT8)Cio2Config->PortCDCtleEnable;
+ FspsUpd->FspsConfig.PchSkyCamPortACtleCapValue = (UINT8)Cio2Config->PortACtleCapValue;
+ FspsUpd->FspsConfig.PchSkyCamPortBCtleCapValue = (UINT8)Cio2Config->PortBCtleCapValue;
+ FspsUpd->FspsConfig.PchSkyCamPortCDCtleCapValue = (UINT8)Cio2Config->PortCDCtleCapValue;
+ FspsUpd->FspsConfig.PchSkyCamPortACtleResValue = (UINT8)Cio2Config->PortACtleResValue;
+ FspsUpd->FspsConfig.PchSkyCamPortBCtleResValue = (UINT8)Cio2Config->PortBCtleResValue;
+ FspsUpd->FspsConfig.PchSkyCamPortCDCtleResValue = (UINT8)Cio2Config->PortCDCtleResValue;
+ FspsUpd->FspsConfig.PchSkyCamPortAClkTrimValue = (UINT8)Cio2Config->PortAClkTrimValue;
+ FspsUpd->FspsConfig.PchSkyCamPortBClkTrimValue = (UINT8)Cio2Config->PortBClkTrimValue;
+ FspsUpd->FspsConfig.PchSkyCamPortCClkTrimValue = (UINT8)Cio2Config->PortCClkTrimValue;
+ FspsUpd->FspsConfig.PchSkyCamPortDClkTrimValue = (UINT8)Cio2Config->PortDClkTrimValue;
+ FspsUpd->FspsConfig.PchSkyCamPortADataTrimValue = (UINT16)Cio2Config->PortADataTrimValue;
+ FspsUpd->FspsConfig.PchSkyCamPortBDataTrimValue = (UINT16)Cio2Config->PortBDataTrimValue;
+ FspsUpd->FspsConfig.PchSkyCamPortCDDataTrimValue = (UINT16)Cio2Config->PortCDDataTrimValue;
+
+ //
+ // Update SCS policies
+ //
+ FspsUpd->FspsConfig.ScsEmmcEnabled = (UINT8)ScsConfig->ScsEmmcEnabled;
+ FspsUpd->FspsConfig.ScsEmmcHs400Enabled = (UINT8)ScsConfig->ScsEmmcHs400Enabled;
+ FspsUpd->FspsConfig.ScsSdCardEnabled = (UINT8)ScsConfig->ScsSdSwitch == 0 ? 0 : 1;
+ FspsUpd->FspsConfig.PchScsEmmcHs400TuningRequired = (UINT8)ScsConfig->ScsEmmcHs400TuningRequired;
+ FspsUpd->FspsConfig.PchScsEmmcHs400DllDataValid = (UINT8)ScsConfig->ScsEmmcHs400DllDataValid;
+ FspsUpd->FspsConfig.PchScsEmmcHs400RxStrobeDll1 = (UINT8)ScsConfig->ScsEmmcHs400RxStrobeDll1;
+ FspsUpd->FspsConfig.PchScsEmmcHs400TxDataDll = (UINT8)ScsConfig->ScsEmmcHs400TxDataDll;
+ FspsUpd->FspsConfig.PchScsEmmcHs400DriverStrength = (UINT8)ScsConfig->ScsEmmcHs400DriverStrength;
+
+ //
+ // Update ISH policies
+ //
+ FspsUpd->FspsConfig.PchIshEnable = (UINT8)IshConfig->Enable;
+ FspsUpd->FspsConfig.PchIshSpiGpioAssign = (UINT8)IshConfig->SpiGpioAssign;
+ FspsUpd->FspsConfig.PchIshUart0GpioAssign = (UINT8)IshConfig->Uart0GpioAssign;
+ FspsUpd->FspsConfig.PchIshUart1GpioAssign = (UINT8)IshConfig->Uart1GpioAssign;
+ FspsUpd->FspsConfig.PchIshI2c0GpioAssign = (UINT8)IshConfig->I2c0GpioAssign;
+ FspsUpd->FspsConfig.PchIshI2c1GpioAssign = (UINT8)IshConfig->I2c1GpioAssign;
+ FspsUpd->FspsConfig.PchIshI2c2GpioAssign = (UINT8)IshConfig->I2c2GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp0GpioAssign = (UINT8)IshConfig->Gp0GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp1GpioAssign = (UINT8)IshConfig->Gp1GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp2GpioAssign = (UINT8)IshConfig->Gp2GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp3GpioAssign = (UINT8)IshConfig->Gp3GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp4GpioAssign = (UINT8)IshConfig->Gp4GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp5GpioAssign = (UINT8)IshConfig->Gp5GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp6GpioAssign = (UINT8)IshConfig->Gp6GpioAssign;
+ FspsUpd->FspsConfig.PchIshGp7GpioAssign = (UINT8)IshConfig->Gp7GpioAssign;
+ FspsUpd->FspsConfig.PchIshPdtUnlock = (UINT8)IshConfig->PdtUnlock;
+
+ //
+ // Update SPI policies
+ //
+ FspsUpd->FspsConfig.ShowSpiController = (UINT8)SpiConfig->ShowSpiController;
+
+ //
+ // Update PCIE RP RootPort policies
+ //
+ for (Index = 0; Index < KBL_PCH_H_PCIE_MAX_ROOT_PORTS; Index ++) {
+ FspsUpd->FspsConfig.PcieRpHotPlug[Index] = (UINT8)PcieRpConfig->RootPort[Index].HotPlug;
+ FspsUpd->FspsConfig.PcieRpPmSci[Index] = (UINT8)PcieRpConfig->RootPort[Index].PmSci;
+ FspsUpd->FspsConfig.PcieRpExtSync[Index] = (UINT8)PcieRpConfig->RootPort[Index].ExtSync;
+ FspsUpd->FspsConfig.PcieRpTransmitterHalfSwing[Index] = (UINT8)PcieRpConfig->RootPort[Index].TransmitterHalfSwing;
+ FspsUpd->FspsConfig.PcieRpClkReqSupport[Index] = (UINT8)PcieRpConfig->RootPort[Index].ClkReqSupported;
+ FspsUpd->FspsConfig.PcieRpClkReqNumber[Index] = (UINT8)PcieRpConfig->RootPort[Index].ClkReqNumber;
+ FspsUpd->FspsConfig.PcieRpClkReqDetect[Index] = (UINT8)PcieRpConfig->RootPort[Index].ClkReqDetect;
+ FspsUpd->FspsConfig.PcieRpAdvancedErrorReporting[Index] = (UINT8)PcieRpConfig->RootPort[Index].AdvancedErrorReporting;
+ FspsUpd->FspsConfig.PcieRpUnsupportedRequestReport[Index] = (UINT8)PcieRpConfig->RootPort[Index].UnsupportedRequestReport;
+ FspsUpd->FspsConfig.PcieRpFatalErrorReport[Index] = (UINT8)PcieRpConfig->RootPort[Index].FatalErrorReport;
+ FspsUpd->FspsConfig.PcieRpNoFatalErrorReport[Index] = (UINT8)PcieRpConfig->RootPort[Index].NoFatalErrorReport;
+ FspsUpd->FspsConfig.PcieRpCorrectableErrorReport[Index] = (UINT8)PcieRpConfig->RootPort[Index].CorrectableErrorReport;
+ FspsUpd->FspsConfig.PcieRpSystemErrorOnFatalError[Index] = (UINT8)PcieRpConfig->RootPort[Index].SystemErrorOnFatalError;
+ FspsUpd->FspsConfig.PcieRpSystemErrorOnNonFatalError[Index] = (UINT8)PcieRpConfig->RootPort[Index].SystemErrorOnNonFatalError;
+ FspsUpd->FspsConfig.PcieRpSystemErrorOnCorrectableError[Index] = (UINT8)PcieRpConfig->RootPort[Index].SystemErrorOnCorrectableError;
+ FspsUpd->FspsConfig.PcieRpMaxPayload[Index] = (UINT8)PcieRpConfig->RootPort[Index].MaxPayload;
+ FspsUpd->FspsConfig.PcieRpDeviceResetPadActiveHigh[Index] = (UINT8)PcieRpConfig->RootPort[Index].DeviceResetPadActiveHigh;
+ FspsUpd->FspsConfig.PcieRpPcieSpeed[Index] = (UINT8)PcieRpConfig->RootPort[Index].PcieSpeed;
+ FspsUpd->FspsConfig.PcieRpGen3EqPh3Method[Index] = (UINT8)PcieRpConfig->RootPort[Index].Gen3EqPh3Method;
+ FspsUpd->FspsConfig.PcieRpPhysicalSlotNumber[Index] = (UINT8)PcieRpConfig->RootPort[Index].PhysicalSlotNumber;
+ FspsUpd->FspsConfig.PcieRpCompletionTimeout[Index] = (UINT8)PcieRpConfig->RootPort[Index].CompletionTimeout;
+ FspsUpd->FspsConfig.PcieRpDeviceResetPad[Index] = (UINT32)PcieRpConfig->RootPort[Index].DeviceResetPad;
+ FspsUpd->FspsConfig.PcieRpAspm[Index] = (UINT8)PcieRpConfig->RootPort[Index].Aspm;
+ FspsUpd->FspsConfig.PcieRpL1Substates[Index] = (UINT8)PcieRpConfig->RootPort[Index].L1Substates;
+ FspsUpd->FspsConfig.PcieRpLtrEnable[Index] = (UINT8)PcieRpConfig->RootPort[Index].LtrEnable;
+ FspsUpd->FspsConfig.PcieRpLtrConfigLock[Index] = (UINT8)PcieRpConfig->RootPort[Index].LtrConfigLock;
+ FspsUpd->FspsTestConfig.PcieRpLtrMaxSnoopLatency[Index] = (UINT16)PcieRpConfig->RootPort[Index].LtrMaxSnoopLatency;
+ FspsUpd->FspsTestConfig.PcieRpLtrMaxNoSnoopLatency[Index] = (UINT16)PcieRpConfig->RootPort[Index].LtrMaxNoSnoopLatency;
+
+ FspsUpd->FspsTestConfig.PcieRpSnoopLatencyOverrideMode[Index] = (UINT8)PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMode;
+ FspsUpd->FspsTestConfig.PcieRpSnoopLatencyOverrideMultiplier[Index] = (UINT8)PcieRpConfig->RootPort[Index].SnoopLatencyOverrideMultiplier;
+ FspsUpd->FspsTestConfig.PcieRpSnoopLatencyOverrideValue[Index] = (UINT16)PcieRpConfig->RootPort[Index].SnoopLatencyOverrideValue;
+
+ FspsUpd->FspsTestConfig.PcieRpNonSnoopLatencyOverrideMode[Index] = (UINT8)PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMode;
+ FspsUpd->FspsTestConfig.PcieRpNonSnoopLatencyOverrideMultiplier[Index] = (UINT8)PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier;
+ FspsUpd->FspsTestConfig.PcieRpNonSnoopLatencyOverrideValue[Index] = (UINT16)PcieRpConfig->RootPort[Index].NonSnoopLatencyOverrideValue;
+
+ FspsUpd->FspsTestConfig.PcieRpSlotPowerLimitScale[Index] = (UINT8)PcieRpConfig->RootPort[Index].SlotPowerLimitScale;
+ FspsUpd->FspsTestConfig.PcieRpSlotPowerLimitValue[Index] = (UINT16)PcieRpConfig->RootPort[Index].SlotPowerLimitValue;
+ FspsUpd->FspsTestConfig.PcieRpUptp[Index] = (UINT8)PcieRpConfig->RootPort[Index].Uptp;
+ FspsUpd->FspsTestConfig.PcieRpDptp[Index] = (UINT8)PcieRpConfig->RootPort[Index].Dptp;
+ }
+
+ //
+ // Update PCIE RP EqPh3LaneParam policies
+ //
+ for (Index = 0; Index < KBL_PCH_H_PCIE_MAX_ROOT_PORTS; Index ++) {
+ FspsUpd->FspsConfig.PcieEqPh3LaneParamCm[Index] = (UINT8)PcieRpConfig->EqPh3LaneParam[Index].Cm;
+ FspsUpd->FspsConfig.PcieEqPh3LaneParamCp[Index] = (UINT8)PcieRpConfig->EqPh3LaneParam[Index].Cp;
+ }
+
+ //
+ // Update PCIE RP SwEqCoeffList policies
+ //
+ for (Index = 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index ++) {
+ FspsUpd->FspsConfig.PcieSwEqCoeffListCm[Index] = (UINT8)PcieRpConfig->SwEqCoeffList[Index].Cm;
+ FspsUpd->FspsConfig.PcieSwEqCoeffListCp[Index] = (UINT8)PcieRpConfig->SwEqCoeffList[Index].Cp;
+ }
+
+ //
+ // Update PCIE RP policies
+ //
+ FspsUpd->FspsTestConfig.PcieEnablePort8xhDecode = (UINT8)PcieRpConfig->EnablePort8xhDecode;
+ FspsUpd->FspsTestConfig.PchPciePort8xhDecodePortIndex = (UINT8)PcieRpConfig->PchPciePort8xhDecodePortIndex;
+ FspsUpd->FspsConfig.PcieDisableRootPortClockGating = (UINT8)PcieRpConfig->DisableRootPortClockGating;
+ FspsUpd->FspsConfig.PcieEnablePeerMemoryWrite = (UINT8)PcieRpConfig->EnablePeerMemoryWrite;
+ FspsUpd->FspsConfig.PcieAllowNoLtrIccPllShutdown = (UINT8)PcieRpConfig->AllowNoLtrIccPllShutdown;
+ FspsUpd->FspsConfig.PcieComplianceTestMode = (UINT8)PcieRpConfig->ComplianceTestMode;
+ FspsUpd->FspsConfig.PcieRpFunctionSwap = (UINT8)PcieRpConfig->RpFunctionSwap;
+ FspsUpd->FspsConfig.PcieDetectTimeoutMs = (UINT16)PcieRpConfig->DetectTimeoutMs;
+ FspsUpd->FspsConfig.PchPcieDeviceOverrideTablePtr = PcieRpConfig->PcieDeviceOverrideTablePtr;
+
+ //
+ // Update Sata Policies
+ //
+ FspsUpd->FspsConfig.SataEnable = (UINT8)SataConfig->Enable;
+ FspsUpd->FspsTestConfig.SataTestMode = (UINT8)SataConfig->TestMode;
+ FspsUpd->FspsConfig.SataSalpSupport = (UINT8)SataConfig->SalpSupport;
+ FspsUpd->FspsConfig.SataPwrOptEnable = (UINT8)SataConfig->PwrOptEnable;
+ FspsUpd->FspsConfig.EsataSpeedLimit = (UINT8)SataConfig->EsataSpeedLimit;
+ FspsUpd->FspsConfig.SataMode = (UINT8)SataConfig->SataMode;
+ FspsUpd->FspsConfig.SataSpeedLimit = (UINT8)SataConfig->SpeedLimit;
+
+ for (Index = 0; Index < PCH_MAX_SATA_PORTS; Index++) {
+ FspsUpd->FspsConfig.SataPortsEnable[Index] = (UINT8)SataConfig->PortSettings[Index].Enable;
+ FspsUpd->FspsConfig.SataPortsHotPlug[Index] = (UINT8)SataConfig->PortSettings[Index].HotPlug;
+ FspsUpd->FspsConfig.SataPortsInterlockSw[Index] = (UINT8)SataConfig->PortSettings[Index].InterlockSw;
+ FspsUpd->FspsConfig.SataPortsExternal[Index] = (UINT8)SataConfig->PortSettings[Index].External;
+ FspsUpd->FspsConfig.SataPortsSpinUp[Index] = (UINT8)SataConfig->PortSettings[Index].SpinUp;
+ FspsUpd->FspsConfig.SataPortsSolidStateDrive[Index] = (UINT8)SataConfig->PortSettings[Index].SolidStateDrive;
+ FspsUpd->FspsConfig.SataPortsDevSlp[Index] = (UINT8)SataConfig->PortSettings[Index].DevSlp;
+ FspsUpd->FspsConfig.SataPortsEnableDitoConfig[Index] = (UINT8)SataConfig->PortSettings[Index].EnableDitoConfig;
+ FspsUpd->FspsConfig.SataPortsDmVal[Index] = (UINT8)SataConfig->PortSettings[Index].DmVal;
+ FspsUpd->FspsConfig.SataPortsDitoVal[Index] = (UINT16)SataConfig->PortSettings[Index].DitoVal;
+ FspsUpd->FspsConfig.SataPortsZpOdd[Index] = (UINT8)SataConfig->PortSettings[Index].ZpOdd;
+ }
+
+ FspsUpd->FspsConfig.SataRstRaidAlternateId = (UINT8)SataConfig->Rst.RaidDeviceId;
+ FspsUpd->FspsConfig.SataRstRaid0 = (UINT8)SataConfig->Rst.Raid0;
+ FspsUpd->FspsConfig.SataRstRaid1 = (UINT8)SataConfig->Rst.Raid1;
+ FspsUpd->FspsConfig.SataRstRaid10 = (UINT8)SataConfig->Rst.Raid10;
+ FspsUpd->FspsConfig.SataRstRaid5 = (UINT8)SataConfig->Rst.Raid5;
+ FspsUpd->FspsConfig.SataRstIrrt = (UINT8)SataConfig->Rst.Irrt;
+ FspsUpd->FspsConfig.SataRstOromUiBanner = (UINT8)SataConfig->Rst.OromUiBanner;
+ FspsUpd->FspsConfig.SataRstOromUiDelay = (UINT8)SataConfig->Rst.OromUiDelay;
+ FspsUpd->FspsConfig.SataRstHddUnlock = (UINT8)SataConfig->Rst.HddUnlock;
+ FspsUpd->FspsConfig.SataRstLedLocate = (UINT8)SataConfig->Rst.LedLocate;
+ FspsUpd->FspsConfig.SataRstIrrtOnly = (UINT8)SataConfig->Rst.IrrtOnly;
+ FspsUpd->FspsConfig.SataRstSmartStorage = (UINT8)SataConfig->Rst.SmartStorage;
+ FspsUpd->FspsConfig.SataRstOptaneMemory = (UINT8)SataConfig->Rst.OptaneMemory;
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ FspsUpd->FspsConfig.SataRstPcieEnable[Index] = (UINT8)SataConfig->RstPcieStorageRemap[Index].Enable;
+ FspsUpd->FspsConfig.SataRstPcieStoragePort[Index] = (UINT8)SataConfig->RstPcieStorageRemap[Index].RstPcieStoragePort;
+ FspsUpd->FspsConfig.SataRstPcieDeviceResetDelay[Index] = (UINT8)SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay;
+ }
+
+ //
+ // Update USB policies
+ //
+ FspsUpd->FspsConfig.PchDisableComplianceMode = (UINT8)UsbConfig->DisableComplianceMode;
+ for (Index = 0; Index < PCH_MAX_USB2_PORTS; Index++) {
+ FspsUpd->FspsConfig.PortUsb20Enable[Index] = (UINT8)UsbConfig->PortUsb20[Index].Enable;
+ FspsUpd->FspsConfig.Usb2OverCurrentPin[Index] = (UINT8)UsbConfig->PortUsb20[Index].OverCurrentPin;
+ FspsUpd->FspsConfig.Usb2AfePetxiset[Index] = (UINT8)UsbConfig->PortUsb20[Index].Afe.Petxiset;
+ FspsUpd->FspsConfig.Usb2AfeTxiset[Index] = (UINT8)UsbConfig->PortUsb20[Index].Afe.Txiset;
+ FspsUpd->FspsConfig.Usb2AfePredeemp[Index] = (UINT8)UsbConfig->PortUsb20[Index].Afe.Predeemp;
+ FspsUpd->FspsConfig.Usb2AfePehalfbit[Index] = (UINT8)UsbConfig->PortUsb20[Index].Afe.Pehalfbit;
+ }
+ for (Index = 0; Index < PCH_MAX_USB3_PORTS; Index++) {
+ FspsUpd->FspsConfig.PortUsb30Enable[Index] = (UINT8)UsbConfig->PortUsb30[Index].Enable;
+ FspsUpd->FspsConfig.Usb3OverCurrentPin[Index] = (UINT8)UsbConfig->PortUsb30[Index].OverCurrentPin;
+ FspsUpd->FspsConfig.Usb3HsioTxDeEmphEnable[Index] = (UINT8)UsbConfig->PortUsb30[Index].HsioTxDeEmphEnable;
+ FspsUpd->FspsConfig.Usb3HsioTxDeEmph[Index] = (UINT8)UsbConfig->PortUsb30[Index].HsioTxDeEmph;
+ FspsUpd->FspsConfig.Usb3HsioTxDownscaleAmpEnable[Index] = (UINT8)UsbConfig->PortUsb30[Index].HsioTxDownscaleAmpEnable;
+ FspsUpd->FspsConfig.Usb3HsioTxDownscaleAmp[Index] = (UINT8)UsbConfig->PortUsb30[Index].HsioTxDownscaleAmp;
+ }
+ FspsUpd->FspsConfig.SsicPortEnable = (UINT8)UsbConfig->SsicConfig.SsicPort[0].Enable;
+ FspsUpd->FspsConfig.XdciEnable = (UINT8)UsbConfig->XdciConfig.Enable;
+
+ //
+ // Update SerialIo policies
+ //
+ for (Index = 0; Index < PCH_SERIALIO_MAX_CONTROLLERS; Index++) {
+ FspsUpd->FspsConfig.SerialIoDevMode[Index] = (UINT8)SerialIoConfig->DevMode[Index];
+ }
+ for (Index = 0; Index < PCH_SERIALIO_MAX_I2C_CONTROLLERS; Index++) {
+ FspsUpd->FspsConfig.SerialIoI2cVoltage[Index] = (UINT8)SerialIoConfig->I2cVoltage[Index];
+ }
+ for (Index = 0; Index < PCH_SERIALIO_MAX_SPI_CONTROLLERS; Index++) {
+ FspsUpd->FspsConfig.SerialIoSpiCsPolarity[Index] = (UINT8)SerialIoConfig->SpiCsPolarity[Index];
+ }
+ for (Index = 0; Index < PCH_SERIALIO_MAX_UART_CONTROLLERS; Index++) {
+ FspsUpd->FspsConfig.SerialIoUartHwFlowCtrl[Index] = (UINT8)SerialIoConfig->UartHwFlowCtrl[Index];
+ }
+ FspsUpd->FspsConfig.SerialIoGpio = (UINT8)SerialIoConfig->Gpio;
+ FspsUpd->FspsConfig.SerialIoDebugUartNumber = (UINT8)SerialIoConfig->DebugUartNumber;
+ FspsUpd->FspsConfig.SerialIoEnableDebugUartAfterPost = (UINT8)SerialIoConfig->EnableDebugUartAfterPost;
+
+ //
+ // Update Interrupt policies
+ //
+ FspsUpd->FspsConfig.DevIntConfigPtr = (UINT32)InterruptConfig->DevIntConfig;
+ FspsUpd->FspsConfig.NumOfDevIntConfig = InterruptConfig->NumOfDevIntConfig;
+ for (Index = 0; Index < PCH_MAX_PXRC_CONFIG; Index ++) {
+ FspsUpd->FspsConfig.PxRcConfig[Index] = (UINT8)InterruptConfig->PxRcConfig[Index];
+ }
+ FspsUpd->FspsConfig.GpioIrqRoute = (UINT8)InterruptConfig->GpioIrqRoute;
+ FspsUpd->FspsConfig.SciIrqSelect = (UINT8)InterruptConfig->SciIrqSelect;
+ FspsUpd->FspsConfig.TcoIrqSelect = (UINT8)InterruptConfig->TcoIrqSelect;
+ FspsUpd->FspsConfig.TcoIrqEnable = (UINT8)InterruptConfig->TcoIrqEnable;
+
+ //
+ // Update LockDown policies
+ //
+ FspsUpd->FspsTestConfig.PchLockDownRtcLock = (UINT8)LockDownConfig->RtcLock;
+ FspsUpd->FspsTestConfig.PchLockDownGlobalSmi = (UINT8)LockDownConfig->GlobalSmi;
+ FspsUpd->FspsTestConfig.PchLockDownBiosInterface = (UINT8)LockDownConfig->BiosInterface;
+ FspsUpd->FspsConfig.PchLockDownBiosLock = (UINT8)LockDownConfig->BiosLock;
+ FspsUpd->FspsConfig.PchLockDownSpiEiss = (UINT8)LockDownConfig->SpiEiss;
+
+ //
+ // Update Dmi policies
+ //
+ FspsUpd->FspsConfig.PchDmiAspm = (UINT8)DmiConfig->DmiAspm;
+ FspsUpd->FspsConfig.PchPwrOptEnable = (UINT8)DmiConfig->PwrOptEnable;
+ if (DmiConfig->LegacyIoLowLatency) {
+ FspsUpd->FspsConfig.PchDmiAspm = 0;
+ FspsUpd->FspsConfig.PchLegacyIoLowLatency = TRUE;
+ }
+
+ //
+ // Update Flash Protection policies
+ //
+ for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; Index ++) {
+ FspsUpd->FspsConfig.PchWriteProtectionEnable[Index] = (UINT8)FlashProtectionConfig->ProtectRange[Index].WriteProtectionEnable;
+ FspsUpd->FspsConfig.PchReadProtectionEnable[Index] = (UINT8)FlashProtectionConfig->ProtectRange[Index].ReadProtectionEnable;
+ FspsUpd->FspsConfig.PchProtectedRangeLimit[Index] = (UINT16)FlashProtectionConfig->ProtectRange[Index].ProtectedRangeLimit;
+ FspsUpd->FspsConfig.PchProtectedRangeBase[Index] = (UINT16)FlashProtectionConfig->ProtectRange[Index].ProtectedRangeBase;
+ }
+
+ //
+ // Update IO Apic policies
+ //
+ FspsUpd->FspsConfig.PchIoApicBdfValid = (UINT8)IoApicConfig->BdfValid;
+ FspsUpd->FspsConfig.PchIoApicBusNumber = (UINT8)IoApicConfig->BusNumber;
+ FspsUpd->FspsConfig.PchIoApicDeviceNumber = (UINT8)IoApicConfig->DeviceNumber;
+ FspsUpd->FspsConfig.PchIoApicFunctionNumber = (UINT8)IoApicConfig->FunctionNumber;
+ FspsUpd->FspsConfig.PchIoApicEntry24_119 = (UINT8)IoApicConfig->IoApicEntry24_119;
+ FspsUpd->FspsConfig.Early8254ClockGatingEnable = (UINT8)IoApicConfig->Early8254ClockGatingEnable;
+ FspsUpd->FspsConfig.PchIoApicId = (UINT8)IoApicConfig->IoApicId;
+ FspsUpd->FspsConfig.PchIoApicRangeSelect = (UINT8)IoApicConfig->ApicRangeSelect;
+
+ //
+ // Update P2sb policies
+ //
+ FspsUpd->FspsTestConfig.PchSbiUnlock = (UINT8)P2sbConfig->SbiUnlock;
+ FspsUpd->FspsTestConfig.PchSbAccessUnlock = (UINT8)P2sbConfig->SbAccessUnlock;
+
+ //
+ // Update Pch General policies
+ //
+ FspsUpd->FspsConfig.PchSubSystemVendorId = (UINT16)PchGeneralConfig->SubSystemVendorId;
+ FspsUpd->FspsConfig.PchSubSystemId = (UINT16)PchGeneralConfig->SubSystemId;
+ FspsUpd->FspsConfig.PchCrid = (UINT8)PchGeneralConfig->Crid;
+
+ //
+ // Update Pm policies
+ //
+ FspsUpd->FspsConfig.PchPmPmeB0S5Dis = (UINT8)PmConfig->WakeConfig.PmeB0S5Dis;
+ FspsUpd->FspsConfig.PchPmWolEnableOverride = (UINT8)PmConfig->WakeConfig.WolEnableOverride;
+ FspsUpd->FspsConfig.PchPmPcieWakeFromDeepSx = (UINT8)PmConfig->WakeConfig.PcieWakeFromDeepSx;
+ FspsUpd->FspsConfig.PchPmWoWlanEnable = (UINT8)PmConfig->WakeConfig.WoWlanEnable;
+ FspsUpd->FspsConfig.PchPmWoWlanDeepSxEnable = (UINT8)PmConfig->WakeConfig.WoWlanDeepSxEnable;
+ FspsUpd->FspsConfig.PchPmLanWakeFromDeepSx = (UINT8)PmConfig->WakeConfig.LanWakeFromDeepSx;
+
+ FspsUpd->FspsConfig.PchPmDeepSxPol = (UINT8)PmConfig->PchDeepSxPol;
+ FspsUpd->FspsConfig.PchPmSlpS3MinAssert = (UINT8)PmConfig->PchSlpS3MinAssert;
+ FspsUpd->FspsConfig.PchPmSlpS4MinAssert = (UINT8)PmConfig->PchSlpS4MinAssert;
+ FspsUpd->FspsConfig.PchPmSlpSusMinAssert = (UINT8)PmConfig->PchSlpSusMinAssert;
+ FspsUpd->FspsConfig.PchPmSlpAMinAssert = (UINT8)PmConfig->PchSlpAMinAssert;
+
+ FspsUpd->FspsConfig.PchPmLpcClockRun = (UINT8)PmConfig->LpcClockRun;
+ FspsUpd->FspsConfig.PchPmSlpStrchSusUp = (UINT8)PmConfig->SlpStrchSusUp;
+ FspsUpd->FspsConfig.PchPmSlpLanLowDc = (UINT8)PmConfig->SlpLanLowDc;
+ FspsUpd->FspsConfig.PchPmPwrBtnOverridePeriod = (UINT8)PmConfig->PwrBtnOverridePeriod;
+ FspsUpd->FspsTestConfig.PchPmDisableEnergyReport = (UINT8)PmConfig->DisableEnergyReport;
+ FspsUpd->FspsConfig.PchPmDisableDsxAcPresentPulldown = (UINT8)PmConfig->DisableDsxAcPresentPulldown;
+ FspsUpd->FspsTestConfig.PchPmPmcReadDisable = (UINT8)PmConfig->PmcReadDisable;
+ FspsUpd->FspsConfig.PchPmDisableNativePowerButton = (UINT8)PmConfig->DisableNativePowerButton;
+ FspsUpd->FspsConfig.PchPmSlpS0Enable = (UINT8)PmConfig->SlpS0Enable;
+ FspsUpd->FspsConfig.PchPmSlpS0VmEnable = (UINT8)PmConfig->SlpS0VmEnable;
+ FspsUpd->FspsConfig.PchPmMeWakeSts = (UINT8)PmConfig->MeWakeSts;
+ FspsUpd->FspsConfig.PchPmWolOvrWkSts = (UINT8)PmConfig->WolOvrWkSts;
+ FspsUpd->FspsConfig.EnableTcoTimer = (UINT8)PmConfig->EnableTcoTimer;
+ FspsUpd->FspsConfig.PchPmPwrCycDur = (UINT8)PmConfig->PchPwrCycDur;
+
+ //
+ // Update Port61h policies
+ //
+ FspsUpd->FspsConfig.PchPort61hEnable = (UINT8)Port61hConfig->Enable;
+
+ //
+ // Update Pch Serial IRQ policies
+ //
+ FspsUpd->FspsConfig.PchSirqEnable = (UINT8)PchSerialIrqConfig->SirqEnable;
+ FspsUpd->FspsConfig.PchSirqMode = (UINT8)PchSerialIrqConfig->SirqMode;
+ FspsUpd->FspsConfig.PchStartFramePulse = (UINT8)PchSerialIrqConfig->StartFramePulse;
+
+ //
+ // Update Pch Thermal policies
+ //
+ FspsUpd->FspsConfig.PchThermalDeviceEnable = (UINT8)PchThermalConfig->ThermalDeviceEnable;
+ FspsUpd->FspsConfig.PchTsmicLock = (UINT8)PchThermalConfig->TsmicLock;
+
+ FspsUpd->FspsConfig.PchT0Level = (UINT16)PchThermalConfig->TTLevels.T0Level;
+ FspsUpd->FspsConfig.PchT1Level = (UINT16)PchThermalConfig->TTLevels.T1Level;
+ FspsUpd->FspsConfig.PchT2Level = (UINT16)PchThermalConfig->TTLevels.T2Level;
+ FspsUpd->FspsConfig.PchTTEnable = (UINT8)PchThermalConfig->TTLevels.TTEnable;
+ FspsUpd->FspsConfig.PchTTState13Enable = (UINT8)PchThermalConfig->TTLevels.TTState13Enable;
+ FspsUpd->FspsConfig.PchTTLock = (UINT8)PchThermalConfig->TTLevels.TTLock;
+ FspsUpd->FspsConfig.TTSuggestedSetting = (UINT8)PchThermalConfig->TTLevels.SuggestedSetting;
+ FspsUpd->FspsConfig.TTCrossThrottling = (UINT8)PchThermalConfig->TTLevels.PchCrossThrottling;
+
+ FspsUpd->FspsConfig.PchDmiTsawEn = (UINT8)PchThermalConfig->DmiHaAWC.DmiTsawEn;
+ FspsUpd->FspsConfig.DmiSuggestedSetting = (UINT8)PchThermalConfig->DmiHaAWC.SuggestedSetting;
+ FspsUpd->FspsConfig.DmiTS0TW = (UINT8)PchThermalConfig->DmiHaAWC.TS0TW;
+ FspsUpd->FspsConfig.DmiTS1TW = (UINT8)PchThermalConfig->DmiHaAWC.TS1TW;
+ FspsUpd->FspsConfig.DmiTS2TW = (UINT8)PchThermalConfig->DmiHaAWC.TS2TW;
+ FspsUpd->FspsConfig.DmiTS3TW = (UINT8)PchThermalConfig->DmiHaAWC.TS3TW;
+
+ FspsUpd->FspsConfig.SataP0T1M = (UINT8)PchThermalConfig->SataTT.P0T1M;
+ FspsUpd->FspsConfig.SataP0T2M = (UINT8)PchThermalConfig->SataTT.P0T2M;
+ FspsUpd->FspsConfig.SataP0T3M = (UINT8)PchThermalConfig->SataTT.P0T3M;
+ FspsUpd->FspsConfig.SataP0TDisp = (UINT8)PchThermalConfig->SataTT.P0TDisp;
+ FspsUpd->FspsConfig.SataP1T1M = (UINT8)PchThermalConfig->SataTT.P1T1M;
+ FspsUpd->FspsConfig.SataP1T2M = (UINT8)PchThermalConfig->SataTT.P1T2M;
+ FspsUpd->FspsConfig.SataP1T3M = (UINT8)PchThermalConfig->SataTT.P1T3M;
+ FspsUpd->FspsConfig.SataP1TDisp = (UINT8)PchThermalConfig->SataTT.P1TDisp;
+ FspsUpd->FspsConfig.SataP0Tinact = (UINT8)PchThermalConfig->SataTT.P0Tinact;
+ FspsUpd->FspsConfig.SataP0TDispFinit = (UINT8)PchThermalConfig->SataTT.P0TDispFinit;
+ FspsUpd->FspsConfig.SataP1Tinact = (UINT8)PchThermalConfig->SataTT.P1Tinact;
+ FspsUpd->FspsConfig.SataP1TDispFinit = (UINT8)PchThermalConfig->SataTT.P1TDispFinit;
+ FspsUpd->FspsConfig.SataThermalSuggestedSetting = (UINT8)PchThermalConfig->SataTT.SuggestedSetting;
+
+ FspsUpd->FspsConfig.PchMemoryThrottlingEnable = (UINT8)PchThermalConfig->MemoryThrottling.Enable;
+ FspsUpd->FspsConfig.PchMemoryPmsyncEnable[0] = (UINT8)PchThermalConfig->MemoryThrottling.TsGpioPinSetting[0].PmsyncEnable;
+ FspsUpd->FspsConfig.PchMemoryPmsyncEnable[1] = (UINT8)PchThermalConfig->MemoryThrottling.TsGpioPinSetting[1].PmsyncEnable;
+ FspsUpd->FspsConfig.PchMemoryC0TransmitEnable[0] = (UINT8)PchThermalConfig->MemoryThrottling.TsGpioPinSetting[0].C0TransmitEnable;
+ FspsUpd->FspsConfig.PchMemoryC0TransmitEnable[1] = (UINT8)PchThermalConfig->MemoryThrottling.TsGpioPinSetting[1].C0TransmitEnable;
+ FspsUpd->FspsConfig.PchMemoryPinSelection[0] = (UINT8)PchThermalConfig->MemoryThrottling.TsGpioPinSetting[0].PinSelection;
+ FspsUpd->FspsConfig.PchMemoryPinSelection[1] = (UINT8)PchThermalConfig->MemoryThrottling.TsGpioPinSetting[1].PinSelection;
+
+ FspsUpd->FspsConfig.PchTemperatureHotLevel = (UINT16)PchThermalConfig->PchHotLevel;
+
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.c
new file mode 100644
index 0000000000..bc2c7f3bec
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.c
@@ -0,0 +1,141 @@
+/** @file
+ Instance of Fsp Policy Initialization Library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PeiFspPolicyInitLib.h>
+
+/**
+ Performs FSP PEI Policy Pre-memory initialization.
+
+ @param[in] FspmUpdDataPtr Pointer to FSPM UPD data.
+**/
+VOID
+EFIAPI
+FspmPolicyInit (
+ IN OUT VOID *FspmUpd
+ )
+{
+ FSPM_UPD *FspmUpdDataPtr;
+ EFI_STATUS Status;
+
+ FspmUpdDataPtr = FspmUpd;
+
+ //
+ // Initialize Intel PEI Platform Policy
+ //
+ PeiPolicyInitPreMem ();
+
+ //
+ // SI Pei Fsp Policy Initialization
+ //
+ Status = PeiFspSiPolicyInitPreMem (FspmUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - SI Pei Fsp Policy in Pre-Memory Initialization fail, Status = %r\n", Status));
+ }
+
+ //
+ // PCH Pei Fsp Policy Initialization
+ //
+ Status = PeiFspPchPolicyInitPreMem (FspmUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - PCH Pei Fsp Policy in Pre-Memory Initialization fail, Status = %r\n", Status));
+ }
+
+ //
+ // Cpu Pei Fsp Policy Initialization
+ //
+ Status = PeiFspCpuPolicyInitPreMem (FspmUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - CPU Pei Fsp Policy in Pre-Memory Initialization fail, Status = %r\n", Status));
+ }
+
+
+ //
+ // ME Pei Fsp Policy Initialization
+ //
+ Status = PeiFspMePolicyInitPreMem (FspmUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - ME Pei Fsp Policy in Pre-Memory Initialization fail, Status = %r\n", Status));
+ }
+
+ //
+ // SystemAgent Pei Fsp Policy Initialization
+ //
+ Status = PeiFspSaPolicyInitPreMem (FspmUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - SystemAgent Pei Fsp Policy in Pre-Memory Initialization fail, Status = %r\n", Status));
+ }
+
+ //
+ // Other Upd Initialization
+ //
+ Status = PeiFspMiscUpdInitPreMem (FspmUpdDataPtr);
+
+}
+
+/**
+ Performs FSP PEI Policy initialization.
+
+ @param[in][out] FspsUpd Pointer UPD data region
+
+**/
+VOID
+EFIAPI
+FspsPolicyInit (
+ IN OUT VOID *FspsUpd
+ )
+{
+ FSPS_UPD *FspsUpdDataPtr;
+ EFI_STATUS Status;
+
+ FspsUpdDataPtr = FspsUpd;
+
+ //
+ // Initialize Intel PEI Platform Policy
+ //
+ PeiPolicyInit ();
+
+ //
+ // PCH Pei Fsp Policy Initialization
+ //
+ Status = PeiFspPchPolicyInit (FspsUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - PCH Pei Fsp Policy iInitialization fail, Status = %r\n", Status));
+ }
+
+ //
+ // ME Pei Fsp Policy Initialization
+ //
+ Status = PeiFspMePolicyInit (FspsUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - ME Pei Fsp Policy Initialization fail, Status = %r\n", Status));
+ }
+
+ //
+ // SystemAgent Pei Fsp Policy Initialization
+ //
+ Status = PeiFspSaPolicyInit (FspsUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - SystemAgent Pei Fsp Policy Initialization fail, Status = %r\n", Status));
+ }
+
+
+ //
+ // Cpu Pei Fsp Policy Initialization
+ //
+ Status = PeiFspCpuPolicyInit (FspsUpdDataPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "ERROR - CPU Pei Fsp Policy Initialization fail, Status = %r\n", Status));
+ }
+
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.h b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.h
new file mode 100644
index 0000000000..a17b642a1d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.h
@@ -0,0 +1,179 @@
+/** @file
+ Internal header file for Fsp Policy Initialization Library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_FSP_POLICY_INIT_LIB_H_
+#define _PEI_FSP_POLICY_INIT_LIB_H_
+
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ConfigBlockLib.h>
+#include "PeiPolicyInitLib.h"
+
+#include <FspEas.h>
+#include <FspmUpd.h>
+#include <FspsUpd.h>
+
+/**
+ Performs FSP SI PEI Policy initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspSiPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ );
+
+/**
+ Performs FSP PCH PEI Policy pre mem initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspPchPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ );
+
+/**
+ Performs FSP PCH PEI Policy initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspPchPolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ );
+
+/**
+ Performs FSP CPU PEI Policy initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspCpuPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ );
+
+
+/**
+ Performs FSP ME PEI Policy pre mem initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspMePolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ );
+
+/**
+ Performs FSP ME PEI Policy initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspMePolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ );
+
+/**
+ Performs FSP SA PEI Policy initialization in pre-memory.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspSaPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ );
+
+/**
+ Performs FSP SA PEI Policy initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspSaPolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ );
+
+
+/**
+ Performs FSP CPU PEI Policy post memory initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspCpuPolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ );
+
+/**
+ Performs FSP Misc UPD initialization.
+
+ @param[in][out] FspmUpd Pointer to FSPM_UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspMiscUpdInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ );
+
+#endif // _PEI_FSP_POLICY_INIT_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.inf
new file mode 100644
index 0000000000..5a77bfb34a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspPolicyInitLib.inf
@@ -0,0 +1,146 @@
+### @file
+# Library functions for Fsp Policy Initialization Library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiFspPolicyInitLib
+ FILE_GUID = 2CB87D67-D1A4-4CD3-8CD7-91A1FA1DF6E0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspPolicyInitLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ PeiFspPolicyInitLib.c
+ PeiFspSiPolicyInitLib.c
+ PeiFspPchPolicyInitLib.c
+ PeiFspCpuPolicyInitLib.c
+ PeiFspMePolicyInitLib.c
+ PeiFspSaPolicyInitLib.c
+ PeiFspMiscUpdInitLib.c
+
+ PeiPolicyInitPreMem.c
+ PeiPolicyInit.c
+ PeiPolicyInit.h
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeFspBinPkg/KabylakeFspBinPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ IoLib
+ PeiServicesLib
+ PcdLib
+ SmbusLib
+ MmPciLib
+ ConfigBlockLib
+ MemoryAllocationLib
+ DebugPrintErrorLevelLib
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdTsegSize ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize ## CONSUMES
+
+[Ppis]
+ gSiPolicyPpiGuid ## CONSUMES
+ gSiPreMemPolicyPpiGuid ## CONSUMES
+
+[Guids]
+ gTraceHubPreMemConfigGuid ## CONSUMES
+ gSmbusPreMemConfigGuid ## CONSUMES
+ gDciPreMemConfigGuid ## CONSUMES
+ gHpetPreMemConfigGuid ## CONSUMES
+ gHsioPciePreMemConfigGuid ## CONSUMES
+ gHsioSataPreMemConfigGuid ## CONSUMES
+ gHsioPreMemConfigGuid ## CONSUMES
+ gPcieRpPreMemConfigGuid ## CONSUMES
+ gLpcPreMemConfigGuid ## CONSUMES
+ gPchGeneralPreMemConfigGuid ## CONSUMES
+ gWatchDogPreMemConfigGuid ## CONSUMES
+ gLanConfigGuid ## CONSUMES
+ gPcieRpConfigGuid ## CONSUMES
+ gSataConfigGuid ## CONSUMES
+ gHdAudioConfigGuid ## CONSUMES
+ gCio2ConfigGuid ## CONSUMES
+ gScsConfigGuid ## CONSUMES
+ gIshConfigGuid ## CONSUMES
+ gSpiConfigGuid ## CONSUMES
+ gSataConfigGuid ## CONSUMES
+ gUsbConfigGuid ## CONSUMES
+ gSerialIoConfigGuid ## CONSUMES
+ gInterruptConfigGuid ## CONSUMES
+ gLockDownConfigGuid ## CONSUMES
+ gSaMiscPeiPreMemConfigGuid ## PRODUCES
+ gMemoryConfigGuid ## CONSUMES
+ gMemoryConfigNoCrcGuid ## CONSUMES
+ gGraphicsPeiConfigGuid ## CONSUMES
+ gMePeiPreMemConfigGuid ## CONSUMES
+ gMePeiConfigGuid ## CONSUMES
+ gAmtPeiConfigGuid ## CONSUMES
+ gDmiConfigGuid ## CONSUMES
+ gFlashProtectionConfigGuid ## CONSUMES
+ gIoApicConfigGuid ## CONSUMES
+ gPmConfigGuid ## CONSUMES
+ gP2sbConfigGuid ## CONSUMES
+ gPchGeneralConfigGuid ## CONSUMES
+ gPort61ConfigGuid ## CONSUMES
+ gSerialIrqConfigGuid ## CONSUMES
+ gThermalConfigGuid ## CONSUMES
+ gCpuSecurityPreMemConfigGuid ## CONSUMES
+ gCpuTxtPreMemConfigGuid ## CONSUMES
+ gCpuConfigGuid ## CONSUMES
+ gBiosGuardConfigGuid ## CONSUMES
+ gCpuOverclockingPreMemConfigGuid ## CONSUMES
+ gCpuConfigLibPreMemConfigGuid ## CONSUMES
+ gCpuSgxConfigGuid ## CONSUMES
+ gCpuPowerMgmtBasicConfigGuid ## CONSUMES
+ gCpuPowerMgmtCustomConfigGuid ## CONSUMES
+ gCpuTestConfigGuid ## CONSUMES
+ gCpuPidTestConfigGuid ## CONSUMES
+ gCpuPowerMgmtTestConfigGuid ## CONSUMES
+ gSmramCpuDataHeaderGuid ## CONSUMES
+ gFspReservedMemoryResourceHobTsegGuid ## CONSUMES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSaPolicyInitLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSaPolicyInitLib.c
new file mode 100644
index 0000000000..3d218f8ba9
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSaPolicyInitLib.c
@@ -0,0 +1,578 @@
+/** @file
+ Implementation of Fsp SA Policy Initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PeiFspPolicyInitLib.h>
+
+#include <Ppi/SiPolicy.h>
+#include <ConfigBlock/MemoryConfig.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmbusLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Pci.h>
+#include <MrcSpdData.h>
+#include <PchAccess.h>
+#include <Ppi/FirmwareVolume.h>
+#include <Pi/PiFirmwareFile.h>
+#include <Pi/PiPeiCis.h>
+
+#define MAX_SPD_PAGE_COUNT (2)
+#define MAX_SPD_PAGE_SIZE (256)
+#define MAX_SPD_SIZE (MAX_SPD_PAGE_SIZE * MAX_SPD_PAGE_COUNT)
+#define SPD_PAGE_ADDRESS_0 (0x6C)
+#define SPD_PAGE_ADDRESS_1 (0x6E)
+#define SPD_DDR3_SDRAM_TYPE_OFFSET (0x02)
+#define SPD_DDR3_SDRAM_TYPE_NUMBER (0x0B)
+#define SPD_DDR4_SDRAM_TYPE_NUMBER (0x0C)
+#define SPD_LPDDR3_SDRAM_TYPE_NUMBER (0xF1)
+#define SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER (0x0F)
+#define XMP_ID_STRING (0x4A0C)
+#define SPD3_MANUF_START (117)
+#define SPD3_MANUF_END (127)
+#define SPD4_MANUF_START (320)
+#define SPD4_MANUF_END (328)
+#define SPDLP_MANUF_START (320)
+#define SPDLP_MANUF_END (328)
+
+GLOBAL_REMOVE_IF_UNREFERENCED const SPD_OFFSET_TABLE mSpdDdr3Table[] = {
+ { 0, 1, (1 << SpdCold),},
+ { 2, 2, (1 << SpdCold) | (1 << SpdFast),},
+ { 3, 41, (1 << SpdCold),},
+ { 60, 63, (1 << SpdCold),},
+ { SPD3_MANUF_START, SPD3_MANUF_END, (1 << SpdCold) | (1 << SpdFast),},
+ { 128, 145, (1 << SpdCold),},
+#ifdef SUPPORT_SPD_CRC
+ { 39, 59, (1 << SpdCold),},
+ { 64, 125, (1 << SpdCold),},
+#endif
+ { 176, 179, (1 << SpdCold),},
+ { 180, 184, (1 << SpdCold),},
+ { 185, 215, (1 << SpdCold),},
+ { 220, 250, (1 << SpdCold),},
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED const SPD_OFFSET_TABLE mSpdDdr4Table[] = {
+ { 0, 1, (1 << SpdCold),},
+ { 2, 2, (1 << SpdCold) | (1 << SpdFast),},
+ { 3, 40, (1 << SpdCold),},
+ { 117, 131, (1 << SpdCold),},
+ { SPD4_MANUF_START, SPD4_MANUF_END, (1 << SpdCold) | (1 << SpdFast),},
+ { 329, 348, (1 << SpdCold),},
+#ifdef SUPPORT_SPD_CRC
+ { 32, 119, (1 << SpdCold),},
+ { 126, 255, (1 << SpdCold),},
+ { 349, 383, (1 << SpdCold),},
+#endif
+ { 384, 387, (1 << SpdCold),},
+ { 388, 389, (1 << SpdCold),},
+ { 393, 431, (1 << SpdCold),},
+ { 440, 478, (1 << SpdCold),},
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED const SPD_OFFSET_TABLE mSpdLpddrTable[] = {
+ { 0, 1, (1 << SpdCold),},
+ { 2, 2, (1 << SpdCold) | (1 << SpdFast),},
+ { 3, 32, (1 << SpdCold),},
+ { 120, 130, (1 << SpdCold),},
+ { SPDLP_MANUF_START, SPDLP_MANUF_END, (1 << SpdCold) | (1 << SpdFast),},
+ { 329, 348, (1 << SpdCold),},
+#ifdef SUPPORT_SPD_CRC
+ { 31, 121, (1 << SpdCold),},
+ { 126, 255, (1 << SpdCold),},
+ { 349, 383, (1 << SpdCold),},
+#endif
+ { 384, 387, (1 << SpdCold),},
+ { 388, 389, (1 << SpdCold),},
+ { 393, 431, (1 << SpdCold),},
+ { 440, 478, (1 << SpdCold),},
+};
+
+
+/**
+ Read the SPD data over the SMBus, at the specified SPD address, starting at
+ the specified starting offset and read the given amount of data.
+
+ @param[in] SpdAddress - SPD SMBUS address
+ @param[in, out] Buffer - Buffer to store the data.
+ @param[in] Start - Starting SPD offset
+ @param[in] Size - The number of bytes of data to read and also the size of the buffer.
+ @param[in, out] Page - The final page that is being pointed to.
+
+ @retval EFI_SUCCESS if the read is successful, otherwise error status.
+**/
+static
+EFI_STATUS
+InternalDoSpdRead (
+ IN const UINT8 SpdAddress,
+ IN OUT UINT8 *const Buffer,
+ IN const UINT16 Start,
+ IN UINT16 Size,
+ IN OUT UINT8 *const Page
+ )
+{
+ EFI_STATUS EfiStatus;
+ BOOLEAN PageUpdate;
+ UINT16 Count;
+ UINT16 Index;
+
+ EfiStatus = EFI_DEVICE_ERROR;
+ if ((Buffer != NULL) && (Start < MAX_SPD_SIZE) && ((Start + Size) < MAX_SPD_SIZE)) {
+ Count = 0;
+ PageUpdate = FALSE;
+ while (Size--) {
+ Index = Start + Count;
+ if ((Index / MAX_SPD_PAGE_SIZE) != *Page) {
+ *Page = (UINT8) (Index / MAX_SPD_PAGE_SIZE);
+ PageUpdate = TRUE;
+ }
+ Index %= MAX_SPD_PAGE_SIZE;
+ if (PageUpdate == TRUE) {
+ PageUpdate = FALSE;
+ SmBusWriteDataByte ((*Page == 0) ? SPD_PAGE_ADDRESS_0 : SPD_PAGE_ADDRESS_1, 0, &EfiStatus);
+ }
+ Buffer[Count] = SmBusReadDataByte (SpdAddress | ((UINT32) Index << 8), &EfiStatus);
+ if (EFI_SUCCESS != EfiStatus) {
+ Buffer[Count] = 0;
+ break;
+ }
+ Count++;
+ }
+ EfiStatus = EFI_SUCCESS;
+ }
+ return (EfiStatus);
+}
+
+/**
+ See if there is valid XMP SPD data.
+
+ @param[in] Debug - Mrc debug structure.
+ @param[in, out] Spd - Mrc SPD structure.
+ @param[in] XmpStart - The current offset in the SPD.
+
+ @retval TRUE if valid, FALSE in not.
+**/
+static
+BOOLEAN
+InternalVerifyXmp (
+ IN OUT MrcSpd *const Spd,
+ IN const UINT16 XmpStart
+ )
+{
+ SPD_EXTREME_MEMORY_PROFILE_HEADER *Header1;
+ SPD_EXTREME_MEMORY_PROFILE_HEADER_2_0 *Header2;
+ BOOLEAN Xmp;
+
+ Xmp = FALSE;
+
+ switch (((UINT8 *)Spd)[2]) {
+ case SPD_DDR3_SDRAM_TYPE_NUMBER:
+ Header1 = &Spd->Ddr3.Xmp.Header;
+ if (XmpStart == ((UINT32) (Header1) - (UINT32) Spd)) {
+ Xmp = TRUE;
+ if ((Header1->XmpRevision.Data & 0xFE) == 0x12) {
+ return (TRUE);
+ } else {
+ Header1->XmpId = 0;
+ Header1->XmpOrgConf.Data = 0;
+ Header1->XmpRevision.Data = 0;
+ }
+ }
+ break;
+ case SPD_DDR4_SDRAM_TYPE_NUMBER:
+ Header2 = &Spd->Ddr4.EndUser.Xmp.Header;
+ if (XmpStart == ((UINT32) (Header2) - (UINT32) Spd)) {
+ Xmp = TRUE;
+ if ((Header2->XmpRevision.Data) == 0x20) {
+ return (TRUE);
+ } else {
+ Header2->XmpId = 0;
+ Header2->XmpOrgConf.Data = 0;
+ Header2->XmpRevision.Data = 0;
+ }
+ }
+ break;
+ case SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER:
+ case SPD_LPDDR3_SDRAM_TYPE_NUMBER:
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+ if (!Xmp) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Read the SPD data over the SMBus, at the given SmBus SPD address and copy the data to the data structure.
+ The SPD data locations read is controlled by the current boot mode.
+
+ @param[in] BootMode - The current MRC boot mode.
+ @param[in] Address - SPD SmBus address offset.
+ @param[in] Buffer - Buffer that contains the data read from the SPD.
+ @param[in] SpdDdr3Table - Indicates which SPD bytes to read.
+ @param[in] SpdDdr3TableSize - Size of SpdDdr3Table in bytes.
+ @param[in] SpdDdr4Table - Indicates which SPD bytes to read.
+ @param[in] SpdDdr4TableSize - Size of SpdDdr4Table in bytes.
+ @param[in] SpdLpddrTable - Indicates which SPD bytes to read.
+ @param[in] SpdLpddrTableSize - Size of SpdLpddrTable in bytes.
+
+ @retval TRUE if the read is successful, otherwise FALSE on error.
+**/
+BOOLEAN
+InternalGetSpdData (
+ IN SPD_BOOT_MODE BootMode,
+ IN UINT8 Address,
+ IN OUT UINT8 *Buffer,
+ IN UINT8 *SpdDdr3Table,
+ IN UINT32 SpdDdr3TableSize,
+ IN UINT8 *SpdDdr4Table,
+ IN UINT32 SpdDdr4TableSize,
+ IN UINT8 *SpdLpddrTable,
+ IN UINT32 SpdLpddrTableSize
+ )
+{
+ const SPD_OFFSET_TABLE *Tbl;
+ const SPD_OFFSET_TABLE *TableSelect;
+ EFI_STATUS Status;
+ UINT32 Byte;
+ UINT32 Stop;
+ UINT8 Page;
+
+ Page = (UINT8) (~0);
+ Status = InternalDoSpdRead (Address, &Buffer[SPD_DDR3_SDRAM_TYPE_OFFSET], 2, 1, &Page);
+ if (EFI_SUCCESS == Status) {
+ switch (Buffer[SPD_DDR3_SDRAM_TYPE_OFFSET]) {
+ case SPD_DDR3_SDRAM_TYPE_NUMBER:
+ case SPD_LPDDR3_SDRAM_TYPE_NUMBER:
+ default:
+ TableSelect = (SPD_OFFSET_TABLE *) SpdDdr3Table;
+ Stop = (SpdDdr3TableSize / sizeof (SPD_OFFSET_TABLE));
+ break;
+ case SPD_DDR4_SDRAM_TYPE_NUMBER:
+ TableSelect = (SPD_OFFSET_TABLE *) SpdDdr4Table;
+ Stop = (SpdDdr4TableSize / sizeof (SPD_OFFSET_TABLE));
+ break;
+ case SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER:
+ TableSelect = (SPD_OFFSET_TABLE *) SpdLpddrTable;
+ Stop = (SpdLpddrTableSize / sizeof (SPD_OFFSET_TABLE));
+ break;
+ }
+ for (Byte = 0; (EFI_SUCCESS == Status) && (Byte < Stop); Byte++) {
+ Tbl = &TableSelect[Byte];
+ if ((1 << BootMode) & Tbl->BootMode) {
+ Status = InternalDoSpdRead (Address, &Buffer[Tbl->Start], Tbl->Start, Tbl->End - Tbl->Start + 1, &Page);
+ if (Status == EFI_SUCCESS) {
+ if (SpdCold == BootMode) {
+ if (FALSE == InternalVerifyXmp ((MrcSpd *) Buffer, Tbl->Start)) {
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ return ((EFI_SUCCESS == Status) ? TRUE : FALSE);
+}
+
+/**
+ Initialize the Smbus PPI and program the Smbus BAR
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database
+**/
+EFI_STATUS
+InternalInitializePchSmbus (
+ VOID
+ )
+{
+ UINTN SmbusRegBase;
+ SmbusRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+
+ ///
+ /// Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves
+ ///
+ MmioAndThenOr32 (SmbusRegBase + R_PCH_SMBUS_BASE, B_PCH_SMBUS_BASE_BAR, PcdGet16 (PcdSmbusBaseAddress));
+
+ MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_IO_SPACE);
+
+ ///
+ /// Reset the SMBus host controller
+ ///
+ MmioOr8 (SmbusRegBase + R_PCH_SMBUS_HOSTC, B_PCH_SMBUS_HOSTC_SSRESET);
+
+ ///
+ /// Enable the SMBus host controller
+ ///
+ MmioAndThenOr8 (
+ SmbusRegBase + R_PCH_SMBUS_HOSTC,
+ (UINT8)(~(B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN)),
+ B_PCH_SMBUS_HOSTC_HST_EN
+ );
+
+ ///
+ /// Clear Status Register before anyone uses the interfaces
+ ///
+ IoWrite8 (PcdGet16(PcdSmbusBaseAddress) + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update Spd Data
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+ @param[in] MemConfigNoCrc Pointer to Mem Config No Crc.
+ @param[in] MiscPeiPreMemConfig Pointer to Misc Config.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval Other The function fail
+**/
+VOID
+EFIAPI
+InternalUpdateSpdData (
+ IN OUT FSPM_UPD *FspmUpd,
+ IN MEMORY_CONFIG_NO_CRC *MemConfigNoCrc,
+ IN SA_MISC_PEI_PREMEM_CONFIG *MiscPeiPreMemConfig
+ )
+{
+ UINT8 Socket;
+ UINT8 *SpdData;
+
+ InternalInitializePchSmbus ();
+
+ DEBUG ((DEBUG_INFO, "Updating UPD:Memory Spd Pointers...\n"));
+ if (FspmUpd == NULL || MemConfigNoCrc == NULL) {
+ DEBUG ((DEBUG_ERROR, "EFI_INVALID_PARAMETER.\n"));
+ DEBUG ((DEBUG_ERROR, "Fail to access SPD from SiPolicyPpi\n"));
+ return;
+ }
+
+ if (*((UINT32 *)MiscPeiPreMemConfig->SpdAddressTable) != 0x0) {
+ //
+ // Update MemConfigNoCrc->SpdData->SpdData
+ //
+ for (Socket = 0; Socket < SA_MC_MAX_SOCKETS; Socket++) {
+ SpdData = (UINT8 *)((UINT32)MemConfigNoCrc->SpdData->SpdData + (Socket * SA_MC_MAX_SPD_SIZE));
+ InternalGetSpdData (
+ 0,
+ MiscPeiPreMemConfig->SpdAddressTable[Socket],
+ (UINT8 *)SpdData,
+ (UINT8 *)&mSpdDdr3Table,
+ sizeof(mSpdDdr3Table),
+ (UINT8 *)&mSpdDdr4Table,
+ sizeof(mSpdDdr4Table),
+ (UINT8 *)&mSpdLpddrTable,
+ sizeof(mSpdLpddrTable)
+ );
+ }
+ }
+
+ FspmUpd->FspmConfig.MemorySpdPtr00 = (UINT32)MemConfigNoCrc->SpdData->SpdData;
+ FspmUpd->FspmConfig.MemorySpdPtr01 = (UINT32)MemConfigNoCrc->SpdData->SpdData + (1 * SA_MC_MAX_SPD_SIZE);
+ FspmUpd->FspmConfig.MemorySpdPtr10 = (UINT32)MemConfigNoCrc->SpdData->SpdData + (2 * SA_MC_MAX_SPD_SIZE);
+ FspmUpd->FspmConfig.MemorySpdPtr11 = (UINT32)MemConfigNoCrc->SpdData->SpdData + (3 * SA_MC_MAX_SPD_SIZE);
+
+ DEBUG ((DEBUG_INFO, "UPD:MemorySpdPtr Updated\n"));
+}
+
+/**
+ Performs FSP SA PEI Policy initialization in pre-memory.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspSaPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ )
+{
+ EFI_STATUS Status;
+ SA_MISC_PEI_PREMEM_CONFIG *MiscPeiPreMemConfig;
+ MEMORY_CONFIGURATION *MemConfig;
+ MEMORY_CONFIG_NO_CRC *MemConfigNoCrc;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
+
+ //
+ // Locate SiPreMemPolicyPpi
+ //
+ SiPreMemPolicyPpi = NULL;
+ MiscPeiPreMemConfig = NULL;
+ MemConfig = NULL;
+ MemConfigNoCrc = NULL;
+
+
+ Status = PeiServicesLocatePpi(
+ &gSiPreMemPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPreMemPolicyPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status) == FALSE) {
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSaMiscPeiPreMemConfigGuid, (VOID *) &MiscPeiPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gMemoryConfigNoCrcGuid, (VOID *) &MemConfigNoCrc);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gMemoryConfigGuid, (VOID *) &MemConfig);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Update UPD:DqPinsInterleaved
+ //
+ FspmUpd->FspmConfig.DqPinsInterleaved = (UINT8)MemConfig->DqPinsInterleaved;
+
+ //
+ // Update UPD:DqPinsInterleaved
+ //
+ FspmUpd->FspmConfig.CaVrefConfig = MemConfig->CaVrefConfig;
+
+ //
+ // Update UPD:MemorySpdPtrXX
+ //
+ InternalUpdateSpdData (FspmUpd, MemConfigNoCrc, MiscPeiPreMemConfig);
+
+ //
+ // Update UPD:MemorySpdDataLen
+ //
+ FspmUpd->FspmConfig.MemorySpdDataLen = SA_MC_MAX_SPD_SIZE;
+
+ //
+ // Update UPD:PlatformMemorySize
+ //
+ //
+ // @todo: This value is used since #183932. Revisit.
+ //
+ FspmUpd->FspmConfig.PlatformMemorySize = MemConfigNoCrc->PlatformMemorySize;
+ FspmUpd->FspmConfig.SaGv = MemConfig->SaGv;
+ FspmUpd->FspmConfig.RMT = (UINT8) MemConfig->RMT;
+ FspmUpd->FspmConfig.DdrFreqLimit = MemConfig->DdrFreqLimit;
+
+ FspmUpd->FspmConfig.SpdProfileSelected = MemConfig->SpdProfileSelected;
+ FspmUpd->FspmConfig.VddVoltage = MemConfig->VddVoltage;
+ FspmUpd->FspmConfig.RefClk = MemConfig->RefClk;
+ FspmUpd->FspmConfig.Ratio = MemConfig->Ratio;
+ FspmUpd->FspmConfig.OddRatioMode = (UINT8) MemConfig->OddRatioMode;
+ FspmUpd->FspmConfig.tCL = (UINT8) MemConfig->tCL;
+ FspmUpd->FspmConfig.tCWL = (UINT8) MemConfig->tCWL;
+ FspmUpd->FspmConfig.tFAW = MemConfig->tFAW;
+ FspmUpd->FspmConfig.tRAS = MemConfig->tRAS;
+ FspmUpd->FspmConfig.tRCDtRP = (UINT8) MemConfig->tRCDtRP;
+ FspmUpd->FspmConfig.tREFI = MemConfig->tREFI;
+ FspmUpd->FspmConfig.tRFC = MemConfig->tRFC;
+ FspmUpd->FspmConfig.tRRD = (UINT8) MemConfig->tRRD;
+ FspmUpd->FspmConfig.tRTP = (UINT8) MemConfig->tRTP;
+ FspmUpd->FspmConfig.tWR = (UINT8) MemConfig->tWR;
+ FspmUpd->FspmConfig.tWTR = (UINT8) MemConfig->tWTR;
+ FspmUpd->FspmConfig.NModeSupport = MemConfig->NModeSupport;
+ FspmUpd->FspmConfig.DllBwEn0 = MemConfig->DllBwEn0;
+ FspmUpd->FspmConfig.DllBwEn1 = MemConfig->DllBwEn1;
+ FspmUpd->FspmConfig.DllBwEn2 = MemConfig->DllBwEn2;
+ FspmUpd->FspmConfig.DllBwEn3 = MemConfig->DllBwEn3;
+ FspmUpd->FspmConfig.EvLoader = (UINT8) MemConfig->EvLoader;
+
+ //
+ // Update UPD:SmramMask
+ //
+ if (MemConfig != NULL) {
+ FspmUpd->FspmConfig.SmramMask = MemConfig->SmramMask;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Performs FSP SA PEI Policy initialization.
+
+ @param[in][out] FspsUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspSaPolicyInit (
+ IN OUT FSPS_UPD *FspsUpd
+ )
+{
+ EFI_STATUS Status;
+ SI_POLICY_PPI *SiPolicyPpi;
+ GRAPHICS_PEI_CONFIG *GtConfig;
+ VTD_CONFIG *Vtd;
+ //
+ // Locate SiPolicyPpi
+ //
+ SiPolicyPpi = NULL;
+ Status = PeiServicesLocatePpi(
+ &gSiPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SiPolicyPpi
+ );
+ if ((Status == EFI_SUCCESS) && (SiPolicyPpi != NULL)) {
+ GtConfig = NULL;
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gGraphicsPeiConfigGuid, (VOID *) &GtConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Vtd = NULL;
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gVtdConfigGuid, (VOID *) &Vtd);
+ ASSERT_EFI_ERROR (Status);
+
+ }
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP UpdatePeiSaPolicy\n"));
+ if (GtConfig != NULL) {
+ //
+ // For FSP, FspsUpd->FspsConfig.PeiGraphicsPeimInit is always enabled as default.
+ //
+ FspsUpd->FspsConfig.PeiGraphicsPeimInit = (UINT8) GtConfig->PeiGraphicsPeimInit; // SA: InternalOnly: For Internal validation we still need to enable both Enable/Disable Cases
+
+ //
+ // Update UPD: VBT & LogoPtr
+ //
+ FspsUpd->FspsConfig.GraphicsConfigPtr = (UINT32) GtConfig->GraphicsConfigPtr;
+ DEBUG(( DEBUG_INFO, "VbtPtr from GraphicsPeiConfig is 0x%x\n", FspsUpd->FspsConfig.GraphicsConfigPtr));
+
+ FspsUpd->FspsConfig.LogoPtr = (UINT32) GtConfig->LogoPtr;
+ FspsUpd->FspsConfig.LogoSize = GtConfig->LogoSize;
+ DEBUG(( DEBUG_INFO, "LogoPtr from PeiFspSaPolicyInit GraphicsPeiConfig is 0x%x\n", FspsUpd->FspsConfig.LogoPtr));
+ DEBUG(( DEBUG_INFO, "LogoSize from PeiFspSaPolicyInit GraphicsPeiConfig is 0x%x\n", FspsUpd->FspsConfig.LogoSize));
+
+
+
+ }
+ if (Vtd != NULL) {
+ FspsUpd->FspsConfig.X2ApicOptOut = (UINT8) Vtd->X2ApicOptOut;
+ FspsUpd->FspsConfig.VtdBaseAddress[0] = Vtd->BaseAddress[0];
+ FspsUpd->FspsConfig.VtdBaseAddress[1] = Vtd->BaseAddress[1];
+ FspsUpd->FspsTestConfig.VtdDisable = (UINT8) Vtd->VtdDisable;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSiPolicyInitLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSiPolicyInitLib.c
new file mode 100644
index 0000000000..49601b1496
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiFspSiPolicyInitLib.c
@@ -0,0 +1,51 @@
+/** @file
+ Implementation of Fsp SI Policy Initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PeiFspPolicyInitLib.h>
+#include <Ppi/SiPolicy.h>
+
+/**
+ Performs FSP SI PEI Policy initialization.
+
+ @param[in][out] FspmUpd Pointer to FSP UPD Data.
+
+ @retval EFI_SUCCESS FSP UPD Data is updated.
+ @retval EFI_NOT_FOUND Fail to locate required PPI.
+ @retval Other FSP UPD Data update process fail.
+**/
+EFI_STATUS
+EFIAPI
+PeiFspSiPolicyInitPreMem (
+ IN OUT FSPM_UPD *FspmUpd
+ )
+{
+ EFI_STATUS Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
+
+ //
+ // Locate SiPolicyPpi
+ //
+ SiPreMemPolicyPpi = NULL;
+ Status = PeiServicesLocatePpi (
+ &gSiPreMemPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPreMemPolicyPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.c
new file mode 100644
index 0000000000..abed092c46
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.c
@@ -0,0 +1,47 @@
+/** @file
+ This file is SampleCode for Intel PEI Platform Policy initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PeiPolicyInit.h"
+
+/**
+ Initialize Intel PEI Platform Policy
+
+**/
+VOID
+EFIAPI
+PeiPolicyInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ SI_POLICY_PPI *SiPolicyPpi;
+
+ //
+ // Call SiCreateConfigBlocks to initialize Silicon Policy structure
+ // and get all Intel default policy settings.
+ //
+ Status = SiCreateConfigBlocks (&SiPolicyPpi);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ //
+ // Install SiPolicyPpi.
+ // While installed, RC assumes the Policy is ready and finalized. So please
+ // update and override any setting before calling this function.
+ //
+ Status = SiInstallPolicyPpi (SiPolicyPpi);
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.h b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.h
new file mode 100644
index 0000000000..e85724411a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInit.h
@@ -0,0 +1,24 @@
+/** @file
+ Header file for the PolicyInitPei PEIM.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_POLICY_INIT_H_
+#define _PEI_POLICY_INIT_H_
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "PeiSiPolicyInit.h"
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitLib.h b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitLib.h
new file mode 100644
index 0000000000..b5a7f4eef3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitLib.h
@@ -0,0 +1,37 @@
+/** @file
+ Header file for the PolicyInitPei Library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _POLICY_INIT_PEI_LIB_H_
+#define _POLICY_INIT_PEI_LIB_H_
+
+/**
+ Initialize Intel PEI Platform Policy
+
+**/
+VOID
+EFIAPI
+PeiPolicyInitPreMem (
+ VOID
+ );
+
+/**
+ Initialize Intel PEI Platform Policy
+
+**/
+VOID
+EFIAPI
+PeiPolicyInit (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitPreMem.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitPreMem.c
new file mode 100644
index 0000000000..35baba3183
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiPolicyInitPreMem.c
@@ -0,0 +1,48 @@
+/** @file
+ This file is SampleCode for Intel PEI Platform Policy initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PeiPolicyInit.h"
+
+/**
+ Initialize Intel PEI Platform Policy
+
+**/
+VOID
+EFIAPI
+PeiPolicyInitPreMem (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
+
+ DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Start in Pre-Memory...\n"));
+ //
+ // Call SiCreatePreMemConfigBlocks to initialize platform policy structure
+ // and get all intel default policy settings.
+ //
+ Status = SiCreatePreMemConfigBlocks (&SiPreMemPolicyPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install SiPreMemPolicyPpi.
+ // While installed, RC assumes the Policy is ready and finalized. So please
+ // update and override any setting before calling this function.
+ //
+ Status = SiPreMemInstallPolicyPpi (SiPreMemPolicyPpi);
+ ASSERT_EFI_ERROR (Status);
+
+
+ DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Done in Pre-Memory\n"));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiSiPolicyInit.h b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiSiPolicyInit.h
new file mode 100644
index 0000000000..4f4a80b9ae
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiFspPolicyInitLib/PeiSiPolicyInit.h
@@ -0,0 +1,24 @@
+/** @file
+ Header file for the PeiSiPolicyInit
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SI_POLICY_INIT_PEI_H_
+#define _SI_POLICY_INIT_PEI_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SiPolicyLib.h>
+
+#endif // _SI_POLICY_INIT_PEI_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c
new file mode 100644
index 0000000000..b7db139ded
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c
@@ -0,0 +1,244 @@
+/** @file
+ This file is PeiSiPolicyLib library creates default settings of RC
+ Policy and installs RC Policy PPI.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PeiSiPolicyLibrary.h"
+#include <Library/PcdLib.h>
+
+/**
+ Get Si config block table total size.
+
+ @retval Size of PCH config block table
+**/
+UINT16
+EFIAPI
+SiGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return (UINT16) sizeof (SI_CONFIG);
+}
+
+EFI_STATUS
+EFIAPI
+LoadSiConfigBlockDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SI_CONFIG *SiConfig;
+
+ SiConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SiConfig->Header.GuidHob.Name = %g\n", &SiConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "SiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SiConfig->Header.GuidHob.Header.HobLength));
+
+ SiConfig->Header.Revision = SI_CONFIG_REVISION;
+ //
+ // Temporary Bus range for silicon initialization.
+ //
+ SiConfig->TempPciBusMin = 2;
+ SiConfig->TempPciBusMax = 10;
+ //
+ // Temporary Memory Base Address for PCI devices to be used to initialize MMIO registers.
+ // Minimum size is 2MB bytes.
+ //
+ SiConfig->TempMemBaseAddr = TEMP_MEM_BASE_ADDRESS;
+ SiConfig->TempMemSize = TEMP_MEM_SIZE;
+ //
+ // Temporary IO Base Address for PCI devices to be used to initialize IO registers.
+ // And size of temporary IO space.
+ //
+ SiConfig->TempIoBaseAddr = TEMP_IO_BASE_ADDRESS;
+ SiConfig->TempIoSize = TEMP_IO_SIZE;
+ //
+ // Check PcdSiCsmEnable to set CSM flag.
+ //
+ if (PcdGetBool (PcdSiCsmEnable)) {
+ SiConfig->CsmFlag = 1;
+ } else {
+ SiConfig->CsmFlag = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SiAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ VOID *ConfigBlockPointer;
+ EFI_STATUS Status;
+ CONFIG_BLOCK_HEADER SiBlock;
+
+ //
+ // Initalize SiBlock
+ //
+ CopyMem (&(SiBlock.GuidHob.Name), &gSiConfigGuid, sizeof (EFI_GUID));
+ SiBlock.GuidHob.Header.HobLength = sizeof (SI_CONFIG);
+ SiBlock.Revision = SI_CONFIG_REVISION;
+ //
+ // Initialize ConfigBlockPointer
+ //
+ ConfigBlockPointer = (VOID *)&SiBlock;
+ //
+ // Add config block fro SiBlock
+ //
+ DEBUG ((DEBUG_INFO, "gSiConfigGuid = %g\n", &gSiConfigGuid));
+ DEBUG ((DEBUG_INFO, "SiConfig->Header.GuidHob.Name = %g\n", &(SiBlock.GuidHob.Name)));
+ Status = AddConfigBlock (ConfigBlockTableAddress, (VOID *) &ConfigBlockPointer);
+ ASSERT_EFI_ERROR (Status);
+
+ LoadSiConfigBlockDefault ((VOID *) ConfigBlockPointer);
+
+ return Status;
+}
+
+/**
+ SiCreateConfigBlocks creates the config blocksg of Silicon Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SiPolicyPpi The pointer to get Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiCreateConfigBlocks (
+ OUT SI_POLICY_PPI **SiPolicyPpi
+ )
+{
+ UINT16 TotalBlockSize;
+ EFI_STATUS Status;
+ SI_POLICY_PPI *SiPolicy;
+ UINT16 RequiredSize;
+
+ SiPolicy = NULL;
+ //
+ // TotalBlockSize = Si, Pch, AMT, ME, SA and CPU config block size.
+ //
+ TotalBlockSize = SiGetConfigBlockTotalSize () +
+ PchGetConfigBlockTotalSize () +
+ MeGetConfigBlockTotalSize () +
+ SaGetConfigBlockTotalSize () +
+ CpuGetConfigBlockTotalSize ();
+ DEBUG ((DEBUG_INFO, "TotalBlockSize = 0x%x\n", TotalBlockSize));
+
+ RequiredSize = sizeof (CONFIG_BLOCK_TABLE_HEADER) + TotalBlockSize;
+
+ Status = CreateConfigBlockTable (RequiredSize, (VOID *) &SiPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // General initialization
+ //
+ SiPolicy->TableHeader.Header.Revision = SI_POLICY_REVISION;
+ //
+ // Add config blocks.
+ //
+ Status = SiAddConfigBlocks ((VOID *) SiPolicy);
+ ASSERT_EFI_ERROR (Status);
+ Status = PchAddConfigBlocks ((VOID *) SiPolicy);
+ ASSERT_EFI_ERROR (Status);
+ Status = MeAddConfigBlocks ((VOID *) SiPolicy);
+ ASSERT_EFI_ERROR (Status);
+ Status = SaAddConfigBlocks ((VOID *) SiPolicy);
+ ASSERT_EFI_ERROR (Status);
+ Status = CpuAddConfigBlocks ((VOID *) SiPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Assignment for returning SaInitPolicy config block base address
+ //
+ *SiPolicyPpi = SiPolicy;
+ return Status;
+}
+
+/**
+ Print out all silicon policy information.
+
+ @param[in] SiPolicyPpi The pointer to Silicon Policy PPI instance
+
+**/
+VOID
+DumpSiPolicy (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ //
+ // Print SI config blocks and serial out.
+ //
+ SiPrintPolicyPpi (SiPolicyPpi);
+ //
+ // Print PCH config blocks and serial out.
+ //
+ PchPrintPolicyPpi (SiPolicyPpi);
+ //
+ // Print ME config blocks and serial out.
+ //
+ MePrintPolicyPpi (SiPolicyPpi);
+ //
+ // Print SA config blocks and serial out.
+ //
+ SaPrintPolicyPpi (SiPolicyPpi);
+ //
+ // Print CPU config block and serial out.
+ //
+ CpuPrintPolicy (SiPolicyPpi);
+}
+
+/**
+ SiInstallPolicyPpi installs SiPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] SiPolicyPpi The pointer to Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiInstallPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *SiPolicyPpiDesc;
+ SI_CONFIG *SiConfig;
+
+ SiPolicyPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ if (SiPolicyPpiDesc == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SiPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ SiPolicyPpiDesc->Guid = &gSiPolicyPpiGuid;
+ SiPolicyPpiDesc->Ppi = SiPolicyPpi;
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSiConfigGuid, (VOID *) &SiConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "Dump Silicon Policy update by Platform...\n"));
+ DumpSiPolicy (SiPolicyPpi);
+
+ //
+ // Install Silicon Policy PPI
+ //
+ Status = PeiServicesInstallPpi (SiPolicyPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf
new file mode 100644
index 0000000000..134f60be5e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf
@@ -0,0 +1,62 @@
+## @file
+# Component description file for the PeiSiPolicyLib library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiSiPolicyLib
+FILE_GUID = 97584FAE-9299-4202-9889-2D339E4BFA5B
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = SiPolicyLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+PeiServicesLib
+BaseMemoryLib
+MemoryAllocationLib
+ConfigBlockLib
+CpuPolicyLib
+CpuPolicyLibPreMem
+PchPolicyLib
+PeiSaPolicyLib
+PeiMePolicyLib
+PcdLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiSiPolicyLib.c
+PeiSiPolicyLibrary.h
+SiPrintPolicy.c
+PeiSiPolicyLibPreMem.c
+
+
+[Guids]
+gSiConfigGuid ## CONSUMES
+
+
+[Ppis]
+gSiPolicyPpiGuid ## PRODUCES
+gSiPreMemPolicyPpiGuid ## PRODUCES
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiCsmEnable ## CONSUMES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibPreMem.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibPreMem.c
new file mode 100644
index 0000000000..3f80b990e9
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibPreMem.c
@@ -0,0 +1,128 @@
+/** @file
+ This file is PeiSiPolicyLib library creates default settings of RC
+ Policy and installs RC Policy PPI.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PeiSiPolicyLibrary.h"
+
+
+/**
+ SiCreatePreMemConfigBlocks creates the config blocksg of Silicon PREMEM Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SiPreMemPolicyPpi The pointer to get Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiCreatePreMemConfigBlocks (
+ OUT SI_PREMEM_POLICY_PPI **SiPreMemPolicyPpi
+ )
+{
+ UINT16 TotalBlockSize;
+ EFI_STATUS Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicy;
+ UINT16 RequiredSize;
+
+ SiPreMemPolicy = NULL;
+ //
+ // TotalBlockSize = Pch , SA, ME and CPU config block size.
+ //
+ TotalBlockSize = PchGetPreMemConfigBlockTotalSize () +
+ MeGetConfigBlockTotalSizePreMem () +
+ SaGetConfigBlockTotalSizePreMem () +
+ CpuGetPreMemConfigBlockTotalSize ();
+ DEBUG ((DEBUG_INFO, "TotalBlockSize = 0x%x\n", TotalBlockSize));
+
+ RequiredSize = sizeof (CONFIG_BLOCK_TABLE_HEADER) + TotalBlockSize;
+
+ Status = CreateConfigBlockTable (RequiredSize, (VOID *)&SiPreMemPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // General initialization
+ //
+ SiPreMemPolicy->TableHeader.Header.Revision = SI_PREMEM_POLICY_REVISION;
+ //
+ // Add config blocks.
+ //
+ Status = PchAddPreMemConfigBlocks ((VOID *) SiPreMemPolicy);
+ ASSERT_EFI_ERROR (Status);
+ Status = MeAddConfigBlocksPreMem ((VOID *) SiPreMemPolicy);
+ ASSERT_EFI_ERROR (Status);
+ Status = SaAddConfigBlocksPreMem ((VOID *) SiPreMemPolicy);
+ ASSERT_EFI_ERROR (Status);
+ Status = CpuAddPreMemConfigBlocks ((VOID *) SiPreMemPolicy);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Assignment for returning SaInitPolicy config block base address
+ //
+ *SiPreMemPolicyPpi = SiPreMemPolicy;
+ return Status;
+}
+
+/**
+ SiPreMemInstallPolicyPpi installs SiPreMemPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] SiPreMemPolicyPpi The pointer to Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SiPreMemInstallPolicyPpi (
+ IN SI_PREMEM_POLICY_PPI *SiPolicyPreMemPpi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *SiPolicyPreMemPpiDesc;
+
+ SiPolicyPreMemPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ if (SiPolicyPreMemPpiDesc == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SiPolicyPreMemPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ SiPolicyPreMemPpiDesc->Guid = &gSiPreMemPolicyPpiGuid;
+ SiPolicyPreMemPpiDesc->Ppi = SiPolicyPreMemPpi;
+
+ //
+ // Print whole PCH_POLICY_PPI and serial out.
+ //
+ PchPreMemPrintPolicyPpi (SiPolicyPreMemPpi);
+ //
+ // Print ME config blocks and serial out.
+ //
+ MePrintPolicyPpiPreMem (SiPolicyPreMemPpi);
+ //
+ // Print whole SI_POLICY_PPI and serial out.
+ //
+ SaPrintPolicyPpiPreMem (SiPolicyPreMemPpi);
+ //
+ // Print whole CPU of SI_PREMEM_POLICY_PPI and serial out.
+ //
+ CpuPreMemPrintPolicy (SiPolicyPreMemPpi);
+
+ //
+ // Install Silicon Policy PPI
+ //
+ Status = PeiServicesInstallPpi (SiPolicyPreMemPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h
new file mode 100644
index 0000000000..4c6ba6309d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h
@@ -0,0 +1,42 @@
+/** @file
+ Header file for the PeiSiPolicyLib library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_SI_POLICY_LIBRARY_H_
+#define _PEI_SI_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/SiPolicyLib.h>
+#include <Library/PchPolicyLib.h>
+#include <Library/PeiMePolicyLib.h>
+#include <Library/PeiSaPolicyLib.h>
+#include <PchAccess.h>
+#include <Library/CpuPolicyLib.h>
+#include <Library/CpuPolicyLibPreMem.h>
+
+#define TEMP_MEM_BASE_ADDRESS 0xFE600000
+#define TEMP_IO_BASE_ADDRESS 0xD000
+
+//
+// IO/MMIO resource limits
+//
+#define TEMP_MEM_SIZE V_PCH_XDCI_MEM_LENGTH
+#define TEMP_IO_SIZE 0x10
+
+#endif // _PEI_SI_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c
new file mode 100644
index 0000000000..16cfb52565
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c
@@ -0,0 +1,46 @@
+/** @file
+ This file is PeiSiPolicyLib library for printing Policy settings.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PeiSiPolicyLibrary.h"
+
+/**
+ Print whole SI_POLICY_PPI and serial out.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+SiPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ SI_CONFIG *SiConfig;
+ EFI_STATUS Status;
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSiConfigGuid, (VOID *) &SiConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------------ Silicon Print Policy Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " TempPciBusMin= %x\n", SiConfig->TempPciBusMin));
+ DEBUG ((DEBUG_INFO, " TempPciBusMax= %x\n", SiConfig->TempPciBusMax));
+ DEBUG ((DEBUG_INFO, " TempMemBaseAddr= %x\n", SiConfig->TempMemBaseAddr));
+ DEBUG ((DEBUG_INFO, " TempMemSize= %x\n", SiConfig->TempMemSize));
+ DEBUG ((DEBUG_INFO, " TempIoBaseAddr= %x\n", SiConfig->TempIoBaseAddr));
+ DEBUG ((DEBUG_INFO, " TempIoSize= %x\n", SiConfig->TempIoSize));
+ DEBUG ((DEBUG_INFO, " CsmFlag= %x\n", SiConfig->CsmFlag));
+ DEBUG ((DEBUG_INFO, "------------------------ Silicon Print Policy End --------------------------\n"));
+ DEBUG_CODE_END ();
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInit.c b/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInit.c
new file mode 100644
index 0000000000..47ca04b98c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInit.c
@@ -0,0 +1,215 @@
+/** @file
+ Source code file for Platform Init PEI module
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <PiPei.h>
+#include <CpuRegs.h>
+#include <PchAccess.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MmPciLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/GpioLib.h>
+#include <Ppi/EndOfPeiPhase.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/ConfigBlockLib.h>
+#include <Ppi/SiPolicy.h>
+#include <SaPolicyCommon.h>
+
+#include <Guid/FirmwareFileSystem2.h>
+
+#include <GpioPinsSklLp.h>
+#include <Library/TimerLib.h>
+
+/**
+ Clear any SMI status or wake status left from boot.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+ClearIchSmiAndWake (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ UINT16 ABase;
+ UINT16 Pm1Sts;
+ UINT32 Pm1Cnt;
+ UINT32 Data32;
+ UINT32 Gpe0Sts;
+ UINT32 SmiSts;
+ UINT16 DevActSts;
+ UINT16 TcoBase;
+ UINT16 Tco1Sts;
+ UINT16 LpcDeviceId;
+ UINTN LanBaseAddress;
+ UINT16 LanPmcs;
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+ if (BootMode == BOOT_ON_S3_RESUME) {
+ return EFI_SUCCESS;
+ }
+
+ PchAcpiBaseGet (&ABase);
+
+ PchTcoBaseGet (&TcoBase);
+
+ //
+ // Read the ACPI registers
+ //
+ Pm1Sts = IoRead16 (ABase + R_PCH_ACPI_PM1_STS);
+ Pm1Cnt = IoRead32 (ABase + R_PCH_ACPI_PM1_CNT);
+
+ Gpe0Sts = IoRead32 (ABase + R_PCH_ACPI_GPE0_STS_127_96);
+ SmiSts = IoRead32 (ABase + R_PCH_SMI_STS);
+
+ Data32 = 0;
+ //
+ // Before clear B_PCH_ACPI_GPE0_STS_127_96_PME_B0, PMES bit of internal device must be cleared at first.
+ //
+ Data32 = (Gpe0Sts & B_PCH_ACPI_GPE0_STS_127_96_PME_B0);
+ if (Data32 != 0) {
+ //
+ // Check if Internal LAN waked up system
+ //
+ LanBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LAN,
+ PCI_FUNCTION_NUMBER_PCH_LAN
+ );
+ LanPmcs = MmioRead16 (LanBaseAddress + R_PCH_LAN_PMCS);
+ if ((LanPmcs & B_PCH_LAN_PMCS_PMES) != 0) {
+ //
+ // Clear PMES bit
+ //
+ MmioOr16 (LanBaseAddress + R_PCH_LAN_PMCS, B_PCH_LAN_PMCS_PMES);
+ DEBUG ((DEBUG_INFO, "Clear LAN PMES bit!\n"));
+ }
+ }
+
+ LpcDeviceId = GetLpcDid ();
+ //
+ // Clear any SMI or wake state from the boot
+ //
+ Pm1Sts |=
+ (
+ B_PCH_ACPI_PM1_STS_WAK |
+ B_PCH_ACPI_PM1_STS_PRBTNOR |
+ B_PCH_ACPI_PM1_STS_RTC |
+ B_PCH_ACPI_PM1_STS_PWRBTN |
+ B_PCH_ACPI_PM1_STS_GBL |
+ B_PCH_ACPI_PM1_STS_TMROF
+ );
+
+ Gpe0Sts |=
+ (
+ B_PCH_ACPI_GPE0_STS_127_96_PME_B0 |
+ B_PCH_ACPI_GPE0_STS_127_96_PME |
+ B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP |
+ B_PCH_ACPI_GPE0_STS_127_96_RI |
+ B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK |
+ B_PCH_ACPI_GPE0_STS_127_96_TC0SCI |
+ B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG |
+ B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE
+ );
+
+ //
+ // PCH Desktop
+ //
+ if (IS_PCH_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) {
+ Gpe0Sts |= B_PCH_ACPI_GPE0_STS_127_96_BATLOW;
+ }
+
+ SmiSts |=
+ (
+ B_PCH_SMI_STS_SMBUS |
+ B_PCH_SMI_STS_PERIODIC |
+ B_PCH_SMI_STS_TCO |
+ B_PCH_SMI_STS_MCSMI |
+ B_PCH_SMI_STS_SWSMI_TMR |
+ B_PCH_SMI_STS_APM |
+ B_PCH_SMI_STS_ON_SLP_EN |
+ B_PCH_SMI_STS_BIOS
+ );
+ //
+ // Write them back
+ //
+ IoWrite16 (ABase + R_PCH_ACPI_PM1_STS, Pm1Sts);
+ IoWrite32 (ABase + R_PCH_ACPI_GPE0_STS_127_96, Gpe0Sts);
+ IoWrite32 (ABase + R_PCH_SMI_STS, SmiSts);
+
+ DevActSts = IoRead16 (ABase + R_PCH_DEVACT_STS);
+ Tco1Sts = IoRead16 (TcoBase + R_PCH_TCO1_STS);
+
+ DevActSts |=
+ (
+ B_PCH_DEVACT_STS_KBC |
+ B_PCH_DEVACT_STS_PIRQDH |
+ B_PCH_DEVACT_STS_PIRQCG |
+ B_PCH_DEVACT_STS_PIRQBF |
+ B_PCH_DEVACT_STS_PIRQAE
+ );
+ Tco1Sts |=
+ (
+ B_PCH_TCO1_STS_DMISERR |
+ B_PCH_TCO1_STS_DMISMI |
+ B_PCH_TCO1_STS_DMISCI |
+ B_PCH_TCO1_STS_BIOSWR |
+ B_PCH_TCO1_STS_NEWCENTURY |
+ B_PCH_TCO1_STS_TIMEOUT |
+ B_PCH_TCO1_STS_TCO_INT |
+ B_PCH_TCO1_STS_SW_TCO_SMI
+ );
+
+ //
+ // clear GPI SMI STS
+ //
+ GpioClearAllGpiSmiSts ();
+
+ IoWrite16 (TcoBase + R_PCH_TCO1_STS, Tco1Sts);
+
+ //
+ // We do not want to write 1 to clear INTRD_DET bit.
+ //
+ IoWrite16 ((UINTN) (TcoBase + R_PCH_TCO2_STS), (UINT16) ~B_PCH_TCO2_STS_INTRD_DET);
+
+ IoWrite16 (ABase + R_PCH_DEVACT_STS, DevActSts);
+
+ //
+ // Clear Power Failure (PWR_FLR), It was used to check S3_Resume State.
+ //
+ // MmioOr8 (
+ // LpcBaseAddress + R_PCH_PMC_GEN_PMCON_B,
+ // B_PCH_PMC_GEN_PMCON_B_PWR_FLR
+ // );
+
+ return EFI_SUCCESS;
+}
+
+VOID
+LateSiliconInit (
+ VOID
+ )
+{
+ ClearIchSmiAndWake ();
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitLib.inf
new file mode 100644
index 0000000000..f26eea6be6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitLib.inf
@@ -0,0 +1,57 @@
+### @file
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = SiliconInitLib
+ FILE_GUID = 72CD3A7B-FEA5-4F5E-9165-4DD12187BB13
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = SiliconInitLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ PeiServicesLib
+ PchCycleDecodingLib
+ PchPcrLib
+ PchPmcLib
+ PchSerialIoLib
+ MmPciLib
+ CpuPlatformLib
+ ConfigBlockLib
+ TimerLib
+ PchInfoLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+ SiliconInit.c
+ SiliconInitPreMem.c
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdTcoBaseAddress ## CONSUMES
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitPreMem.c b/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitPreMem.c
new file mode 100644
index 0000000000..616584ffe7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Library/SiliconInitLib/SiliconInitPreMem.c
@@ -0,0 +1,240 @@
+/** @file
+ Source code file for Platform Init Pre-Memory PEI module
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <PiPei.h>
+#include <PchAccess.h>
+#include <SaPolicyCommon.h>
+#include <CpuAccess.h>
+#include <SaAccess.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPmcLib.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Include/Library/ConfigBlockLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PchSerialIoLib.h>
+
+//@todo it should be moved to Si Pkg.
+/**
+ Early Platform PCH initialization
+**/
+VOID
+EarlySiliconInit (
+ VOID
+ )
+{
+ UINT16 Data16;
+ UINT8 Data8;
+ UINTN LpcBaseAddress;
+ UINTN P2sbBase;
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ ///
+ /// Program bar
+ ///
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBREG_BAR, PCH_PCR_BASE_ADDRESS);
+ MmioOr8 (P2sbBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ ///
+ /// Program ACPI BASE
+ ///
+ PchAcpiBaseSet (PcdGet16 (PcdAcpiBaseAddress));
+
+ ///
+ /// Program PWRM BASE
+ ///
+ PchPwrmBaseSet (PCH_PWRM_BASE_ADDRESS);
+
+ ///
+ /// Program TCO BASE
+ ///
+ PchTcoBaseSet (PcdGet16 (PcdTcoBaseAddress));
+
+ ///
+ /// LPC I/O Configuration
+ ///
+ PchLpcIoDecodeRangesSet (
+ (V_PCH_LPC_IOD_LPT_378 << N_PCH_LPC_IOD_LPT) |
+ (V_PCH_LPC_IOD_COMB_3E8 << N_PCH_LPC_IOD_COMB) |
+ (V_PCH_LPC_IOD_COMA_3F8 << N_PCH_LPC_IOD_COMA)
+ );
+
+ PchLpcIoEnableDecodingSet (
+ B_PCH_LPC_IOE_ME2 |
+ B_PCH_LPC_IOE_SE |
+ B_PCH_LPC_IOE_ME1 |
+ B_PCH_LPC_IOE_KE |
+ B_PCH_LPC_IOE_HGE |
+ B_PCH_LPC_IOE_LGE |
+ B_PCH_LPC_IOE_FDE |
+ B_PCH_LPC_IOE_PPE |
+ B_PCH_LPC_IOE_CBE |
+ B_PCH_LPC_IOE_CAE
+ );
+
+
+ ///
+ /// Enable the upper 128-byte bank of RTC RAM
+ ///
+ PchPcrAndThenOr32 (PID_RTC, R_PCH_PCR_RTC_CONF, (UINT32)~0, B_PCH_PCR_RTC_CONF_UCMOS_EN);
+
+ ///
+ /// Disable the Watchdog timer expiration from causing a system reset
+ ///
+ PchPcrAndThenOr32 (PID_ITSS, R_PCH_PCR_ITSS_GIC, (UINT32)~0, B_PCH_PCR_ITSS_GIC_AME);
+
+ ///
+ /// Halt the TCO timer
+ ///
+ Data16 = IoRead16 (PcdGet16 (PcdTcoBaseAddress) + R_PCH_TCO1_CNT);
+ Data16 |= B_PCH_TCO_CNT_TMR_HLT;
+ IoWrite16 (PcdGet16 (PcdTcoBaseAddress) + R_PCH_TCO1_CNT, Data16);
+
+ ///
+ /// Clear the Second TO status bit
+ ///
+ IoWrite8 (PcdGet16 (PcdTcoBaseAddress) + R_PCH_TCO2_STS, B_PCH_TCO2_STS_SECOND_TO);
+
+ ///
+ /// Disable SERR NMI and IOCHK# NMI in port 61
+ ///
+ Data8 = IoRead8 (R_PCH_NMI_SC);
+ Data8 |= (B_PCH_NMI_SC_PCI_SERR_EN | B_PCH_NMI_SC_IOCHK_NMI_EN);
+ IoWrite8 (R_PCH_NMI_SC, Data8);
+
+ PchPcrAndThenOr32 (PID_ITSS, R_PCH_PCR_ITSS_GIC, (UINT32)~B_PCH_PCR_ITSS_GIC_AME, 0);
+
+ //
+ // Program timer 1 as refresh timer
+ //
+ IoWrite8 (0x43, 0x54);
+ IoWrite8 (0x41, 0x12);
+
+}
+
+// @todo: It should be moved Policy Init.
+/**
+ Initialize the GPIO IO selection, GPIO USE selection, and GPIO signal inversion registers
+
+**/
+VOID
+SiliconInit (
+ VOID
+ )
+{
+ UINT16 Data16;
+ UINT8 Data8;
+ UINTN LpcBaseAddress;
+ UINT16 ABase;
+ UINT16 Pm1Sts;
+ UINT32 Pm1Cnt;
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ ///
+ /// LPC I/O Configuration
+ ///
+ PchLpcIoDecodeRangesSet (
+ (V_PCH_LPC_IOD_LPT_378 << N_PCH_LPC_IOD_LPT) |
+ (V_PCH_LPC_IOD_COMB_3E8 << N_PCH_LPC_IOD_COMB) |
+ (V_PCH_LPC_IOD_COMA_3F8 << N_PCH_LPC_IOD_COMA)
+ );
+ PchLpcIoEnableDecodingSet (
+ B_PCH_LPC_IOE_ME2 |
+ B_PCH_LPC_IOE_SE |
+ B_PCH_LPC_IOE_ME1 |
+ B_PCH_LPC_IOE_KE |
+ B_PCH_LPC_IOE_HGE |
+ B_PCH_LPC_IOE_LGE |
+ B_PCH_LPC_IOE_FDE |
+ B_PCH_LPC_IOE_PPE |
+ B_PCH_LPC_IOE_CBE |
+ B_PCH_LPC_IOE_CAE
+ );
+ ///
+ /// Enable the upper 128-byte bank of RTC RAM
+ ///
+ PchPcrAndThenOr32 (PID_RTC, R_PCH_PCR_RTC_CONF, (UINT32)~0, B_PCH_PCR_RTC_CONF_UCMOS_EN);
+ ///
+ /// Disable the Watchdog timer expiration from causing a system reset
+ ///
+ PchPcrAndThenOr32 (PID_SMB, R_PCH_PCR_SMBUS_GC, (UINT32)~0, B_PCH_PCR_SMBUS_GC_NR);
+
+ ///
+ /// Halt the TCO timer
+ ///
+ Data16 = IoRead16 (PcdGet16 (PcdTcoBaseAddress) + R_PCH_TCO1_CNT);
+ Data16 |= B_PCH_TCO_CNT_TMR_HLT;
+ IoWrite16 (PcdGet16 (PcdTcoBaseAddress) + R_PCH_TCO1_CNT, Data16);
+ ///
+ /// Clear the Second TO status bit
+ ///
+ IoWrite8 (PcdGet16 (PcdTcoBaseAddress) + R_PCH_TCO2_STS, B_PCH_TCO2_STS_SECOND_TO);
+ ///
+ /// Disable SERR NMI and IOCHK# NMI in port 61
+ ///
+ Data8 = IoRead8 (R_PCH_NMI_SC);
+ Data8 |= (B_PCH_NMI_SC_PCI_SERR_EN | B_PCH_NMI_SC_IOCHK_NMI_EN);
+ IoWrite8 (R_PCH_NMI_SC, Data8);
+
+
+ ///
+ /// Clear all pending SMI. On S3 clear power button enable so it will not generate an SMI.
+ ///
+ IoWrite16 (PcdGet16 (PcdAcpiBaseAddress) + R_PCH_ACPI_PM1_EN, 0);
+ IoWrite32 (PcdGet16 (PcdAcpiBaseAddress) + R_PCH_ACPI_GPE0_EN_127_96, 0);
+ ///----------------------------------------------------------------------------------
+ ///
+ /// BIOS should check the WAK_STS bit in PM1_STS[15] (PCH register ABASE+00h) before memory
+ /// initialization to determine if ME has reset the system while the host was in a sleep state.
+ /// If WAK_STS is not set, BIOS should ensure a non-sleep exit path is taken by overwriting
+ /// PM1_CNT[12:10] (PCH register ABASE+04h) to 111b to force an s5 exit.
+ ///
+ PchAcpiBaseGet (&ABase);
+ Pm1Sts = IoRead16 (ABase + R_PCH_ACPI_PM1_STS);
+ if ((Pm1Sts & B_PCH_ACPI_PM1_STS_WAK) == 0) {
+ Pm1Cnt = IoRead32 (ABase + R_PCH_ACPI_PM1_CNT);
+ Pm1Cnt |= V_PCH_ACPI_PM1_CNT_S5;
+ IoWrite32 (ABase + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
+ }
+
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/License.txt b/Silicon/Intel/KabylakeSiliconPkg/License.txt
new file mode 100644
index 0000000000..3bb2e6d1ea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/License.txt
@@ -0,0 +1,25 @@
+Copyright (c) 2017, Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Me/Include/ConfigBlock/MePeiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/ConfigBlock/MePeiConfig.h
new file mode 100644
index 0000000000..2ec0d556b1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/ConfigBlock/MePeiConfig.h
@@ -0,0 +1,135 @@
+/** @file
+ ME config block for PEI phase
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _ME_PEI_CONFIG_H_
+#define _ME_PEI_CONFIG_H_
+
+#define ME_PEI_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gMePeiPreMemConfigGuid;
+
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+
+#pragma pack (push,1)
+/**
+ ME PEI Pre-Mem Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ UINT32 HeciTimeouts : 1; ///< 0: Disable; <b>1: Enable</b> - HECI Send/Receive Timeouts.
+
+ /**
+ <b>(Test)</b>
+ <b>0: Disabled</b>
+ 1: ME DID init stat 0 - Success
+ 2: ME DID init stat 1 - No Memory in Channels
+ 3: ME DID init stat 2 - Memory Init Error
+ 4: ME DID init stat 3 - Memory not preserved across reset
+ **/
+ UINT32 DidInitStat : 8;
+ /**
+ <b>(Test)</b>
+ <b>0: Set to 0 to enable polling for CPU replacement</b>
+ 1: Set to 1 will disable polling for CPU replacement
+ **/
+ UINT32 DisableCpuReplacedPolling : 1;
+ UINT32 SendDidMsg : 1; ///< <b>(Test)</b> 0: Disable; <b>1: Enable</b> - Enable/Disable to send DID message.
+ /**
+ <b>(Test)</b>
+ <b>0: Set to 0 to enable retry mechanism for HECI APIs</b>
+ 1: Set to 1 will disable retry mechanism for HECI APIs
+ **/
+ UINT32 DisableHeciRetry : 1;
+ /**
+ <b>(Test)</b>
+ <b>0: ME BIOS will check each messages before sending</b>
+ 1: ME BIOS always sends messages without checking
+ **/
+ UINT32 DisableMessageCheck : 1;
+ /**
+ <b>(Test)</b>
+ The SkipMbpHob policy determines whether ME BIOS Payload data will be requested during boot
+ in a MBP message. If set to 1, BIOS will send the MBP message with SkipMbp flag
+ set causing CSME to respond with MKHI header only and no MBP data
+ <b>0: ME BIOS will keep MBP and create HOB for MBP data</b>
+ 1: ME BIOS will skip MBP data
+ **/
+ UINT32 SkipMbpHob : 1;
+
+ UINT32 HeciCommunication2 : 1; ///< <b>(Test)</b> <b>0: Disable</b>; 1: Enable - Enable/Disable HECI2.
+ UINT32 KtDeviceEnable : 1; ///< <b>(Test)</b> 0: Disable; <b>1: Enable</b> - Enable/Disable Kt Device.
+ UINT32 IderDeviceEnable : 1; ///< <b>(Test)</b> 0: Disable; <b>1: Enable</b> - Enable/Disable IDEr.
+ UINT32 RsvdBits : 15; ///< Reserved for future use & Config block alignment
+
+ UINT32 Heci1BarAddress; ///< HECI1 BAR address.
+ UINT32 Heci2BarAddress; ///< HECI2 BAR address.
+ UINT32 Heci3BarAddress; ///< HECI3 BAR address.
+} ME_PEI_PREMEM_CONFIG;
+#pragma pack (pop)
+
+
+#define ME_PEI_CONFIG_REVISION 3
+extern EFI_GUID gMePeiConfigGuid;
+
+#pragma pack (push,1)
+/**
+ ME Pei Post-Mem Configuration Structure.
+
+ <b>Revision 1:</b>
+ - Initial version.
+ <b>Revision 2:</b>
+ - Add MeUnconfigOnRtcClear policy.
+ <b>Revision 3:</b>
+ - Add MeUnconfigIsValid to indicate if MeUnconfigOnRtcClear item is valid.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ UINT32 EndOfPostMessage : 2; ///< 0: Disabled; 1: Send in PEI; <b>2: Send in DXE</b> - Send EOP at specific phase.
+ /**
+ HECI3 state from Mbp for reference in S3 path only
+ <b>0: Disabled</b>; 1: Enabled
+ **/
+ UINT32 Heci3Enabled : 1;
+ UINT32 DisableD0I3SettingForHeci : 1; ///< <b>(Test)</b> <b>0: Disable</b>; 1: Enable - Enable/Disable D0i3 for HECI.
+ /**
+ Enable/Disable Me Unconfig On Rtc Clear. If enabled, BIOS will send MeUnconfigOnRtcClearDisable Msg with parameter 0.
+ It will cause ME to unconfig if RTC is cleared.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 MeUnconfigOnRtcClear : 1;
+ /**
+ Check if MeUnconfigOnRtcClear is valid. The item could be not valid due to CMOS is clear.
+ In that case, MeUnconfigOnRtcClear item will be ignored.
+ - 0: Cmos is clear. Not Valid.
+ - <b>1: Valid</b>
+ **/
+ UINT32 MeUnconfigIsValid : 1;
+ UINT32 RsvdBits : 26; ///< Reserved for future use & Config block alignment
+} ME_PEI_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _ME_PEI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Me/Include/Library/PeiMePolicyLib.h b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/Library/PeiMePolicyLib.h
new file mode 100644
index 0000000000..20afe4c46e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/Library/PeiMePolicyLib.h
@@ -0,0 +1,92 @@
+/** @file
+ Prototype of the MePolicyLibPei library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_ME_POLICY_LIB_H_
+#define _PEI_ME_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+#include <Library/ConfigBlockLib.h>
+
+/**
+ This function prints the PEI phase PreMem policy.
+
+ @param[in] SiPolicyPreMemPpi The RC PreMem Policy PPI instance
+**/
+VOID
+EFIAPI
+MePrintPolicyPpiPreMem (
+ IN SI_PREMEM_POLICY_PPI *SiPolicyPreMemPpi
+ );
+
+/**
+ This function prints the PEI phase policy.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+MePrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ Get Me config block table total size.
+
+ @retval Size of Me config block table
+**/
+UINT16
+EFIAPI
+MeGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ Get ME config block table total size.
+
+ @retval Size of ME config block table
+**/
+UINT16
+EFIAPI
+MeGetConfigBlockTotalSizePreMem (
+ VOID
+ );
+
+/**
+ MeAddConfigBlocksPreMem add all ME config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add ME config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+MeAddConfigBlocksPreMem (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+/**
+ MeAddConfigBlocks add all ME config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add ME config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+MeAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+#endif // _PEI_ME_POLICY_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Me/Include/MeChipset.h b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/MeChipset.h
new file mode 100644
index 0000000000..11ee04ad12
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/MeChipset.h
@@ -0,0 +1,48 @@
+/** @file
+ Chipset definition for ME Devices.
+
+ Conventions:
+
+ - Prefixes:
+ - Definitions beginning with "R_" are registers
+ - Definitions beginning with "B_" are bits within registers
+ - Definitions beginning with "V_" are meaningful values of bits within the registers
+ - Definitions beginning with "S_" are register sizes
+ - Definitions beginning with "N_" are the bit position
+ - In general, ME registers are denoted by "_ME_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_ME_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "PCH_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "PCH_LP_" in register/bit names.
+ e.g., "_ME_PCH_H_", "_ME_PCH_LP_"
+ Registers / bits names without _PCH_H_ or _PCH_LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_ME_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _ME_CHIPSET_H_
+#define _ME_CHIPSET_H_
+
+#define ME_BUS 0
+#define ME_DEVICE_NUMBER 22
+#define HECI_MIN_FUNC 0
+#define HECI_MAX_FUNC 5
+
+#define HECI_FUNCTION_NUMBER 0x00
+#define HECI2_FUNCTION_NUMBER 0x01
+#define IDER_FUNCTION_NUMBER 0x02
+#define SOL_FUNCTION_NUMBER 0x03
+#define HECI3_FUNCTION_NUMBER 0x04
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Me/Include/MePolicyCommon.h b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/MePolicyCommon.h
new file mode 100644
index 0000000000..0243982c80
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Me/Include/MePolicyCommon.h
@@ -0,0 +1,31 @@
+/** @file
+ Definition for ME common policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _ME_POLICY_COMMON_H_
+#define _ME_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "ConfigBlock/MePeiConfig.h"
+
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+
+#endif // _ME_POLICY_COMMON_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.c
new file mode 100644
index 0000000000..94a84a0478
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.c
@@ -0,0 +1,261 @@
+/** @file
+ This file is PeiMePolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiMePolicyLibrary.h"
+
+/**
+ Load default settings for ME config block in pre-mem phase.
+
+ @param[in] ConfigBlockPointer The pointer to the config block
+**/
+VOID
+LoadMePeiPreMemDefault (
+ IN VOID *ConfigBlockPointer
+ );
+
+/**
+ Load default settings for ME config block in PEI phase.
+
+ @param[in] ConfigBlockPointer The pointer to the config block
+**/
+VOID
+LoadMePeiDefault (
+ IN VOID *ConfigBlockPointer
+ );
+
+STATIC COMPONENT_BLOCK_ENTRY mMeCompontBlockPreMemBlocks [] = {
+ {&gMePeiPreMemConfigGuid, sizeof (ME_PEI_PREMEM_CONFIG), ME_PEI_PREMEM_CONFIG_REVISION, LoadMePeiPreMemDefault}
+};
+
+STATIC COMPONENT_BLOCK_ENTRY mMeCompontBlockBlocks [] = {
+ {&gMePeiConfigGuid, sizeof (ME_PEI_CONFIG), ME_PEI_CONFIG_REVISION, LoadMePeiDefault}
+};
+
+/**
+ Load default settings for ME config block in pre-mem phase.
+
+ @param[in] ConfigBlockPointer The pointer to the config block
+**/
+VOID
+LoadMePeiPreMemDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ ME_PEI_PREMEM_CONFIG *MePeiPreMemConfig;
+ MePeiPreMemConfig = ConfigBlockPointer;
+
+ MePeiPreMemConfig->HeciTimeouts = 1;
+
+ MePeiPreMemConfig->Heci1BarAddress = 0xFED1A000;
+ MePeiPreMemConfig->Heci2BarAddress = 0xFED1B000;
+ MePeiPreMemConfig->Heci3BarAddress = 0xFED1C000;
+
+ //
+ // Test policies
+ //
+ MePeiPreMemConfig->SendDidMsg = 1;
+
+ MePeiPreMemConfig->KtDeviceEnable = 1;
+ MePeiPreMemConfig->IderDeviceEnable = 1;
+
+
+}
+
+/**
+ Load default settings for ME config block in PEI phase.
+
+ @param[in] ConfigBlockPointer The pointer to the config block
+**/
+VOID
+LoadMePeiDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ ME_PEI_CONFIG *MePeiConfig;
+ MePeiConfig = ConfigBlockPointer;
+
+ MePeiConfig->EndOfPostMessage = 1;
+ MePeiConfig->MeUnconfigOnRtcClear = 1;
+ MePeiConfig->MeUnconfigIsValid = 1;
+}
+
+/**
+ Dump values of ME config block in pre-mem phase.
+
+ @param[in] MePeiPreMemConfig The pointer to the config block
+**/
+VOID
+EFIAPI
+PrintMePeiPreMemConfig (
+ IN ME_PEI_PREMEM_CONFIG *MePeiPreMemConfig
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ DEBUG ((DEBUG_INFO, "------------------------ ME_PEI_PREMEM_CONFIG -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : 0x%x\n", MePeiPreMemConfig->Header.Revision));
+ ASSERT (MePeiPreMemConfig->Header.Revision == ME_PEI_PREMEM_CONFIG_REVISION);
+
+ DEBUG ((DEBUG_INFO, " HeciTimeouts : 0x%x\n", MePeiPreMemConfig->HeciTimeouts));
+ DEBUG ((DEBUG_INFO, " DidInitStat : 0x%x\n", MePeiPreMemConfig->DidInitStat));
+ DEBUG ((DEBUG_INFO, " DisableCpuReplacedPolling : 0x%x\n", MePeiPreMemConfig->DisableCpuReplacedPolling));
+ DEBUG ((DEBUG_INFO, " SendDidMsg : 0x%x\n", MePeiPreMemConfig->SendDidMsg));
+ DEBUG ((DEBUG_INFO, " DisableHeciRetry : 0x%x\n", MePeiPreMemConfig->DisableHeciRetry));
+ DEBUG ((DEBUG_INFO, " DisableMessageCheck : 0x%x\n", MePeiPreMemConfig->DisableMessageCheck));
+ DEBUG ((DEBUG_INFO, " SkipMbpHob : 0x%x\n", MePeiPreMemConfig->SkipMbpHob));
+ DEBUG ((DEBUG_INFO, " HeciCommunication2 : 0x%x\n", MePeiPreMemConfig->HeciCommunication2));
+ DEBUG ((DEBUG_INFO, " KtDeviceEnable : 0x%x\n", MePeiPreMemConfig->KtDeviceEnable));
+ DEBUG ((DEBUG_INFO, " IderDeviceEnable : 0x%x\n", MePeiPreMemConfig->IderDeviceEnable));
+ DEBUG ((DEBUG_INFO, " Heci1BarAddress : 0x%x\n", MePeiPreMemConfig->Heci1BarAddress));
+ DEBUG ((DEBUG_INFO, " Heci2BarAddress : 0x%x\n", MePeiPreMemConfig->Heci2BarAddress));
+ DEBUG ((DEBUG_INFO, " Heci3BarAddress : 0x%x\n", MePeiPreMemConfig->Heci3BarAddress));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Dump values of ME config block in PEI phase.
+
+ @param[in] MePeiConfig The pointer to the config block
+**/
+VOID
+EFIAPI
+PrintMePeiConfig (
+ IN ME_PEI_CONFIG *MePeiConfig
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ DEBUG ((DEBUG_INFO, "------------------------ ME_PEI_CONFIG -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : 0x%x\n", MePeiConfig->Header.Revision));
+ ASSERT (MePeiConfig->Header.Revision == ME_PEI_CONFIG_REVISION);
+
+ DEBUG ((DEBUG_INFO, " EndOfPostMessage : 0x%x\n", MePeiConfig->EndOfPostMessage));
+ DEBUG ((DEBUG_INFO, " Heci3Enabled : 0x%x\n", MePeiConfig->Heci3Enabled));
+ DEBUG ((DEBUG_INFO, " DisableD0I3SettingForHeci : 0x%x\n", MePeiConfig->DisableD0I3SettingForHeci));
+ DEBUG ((DEBUG_INFO, " MeUnconfigOnRtcClear : 0x%x\n", MePeiConfig->MeUnconfigOnRtcClear));
+ DEBUG ((DEBUG_INFO, " MeUnconfigIsValid : 0x%x\n", MePeiConfig->MeUnconfigIsValid));
+
+ DEBUG_CODE_END ();
+}
+
+/**
+ Print PEI ME config block
+
+ @param[in] SiPolicyPpiPreMem The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+MePrintPolicyPpiPreMem (
+ IN SI_PREMEM_POLICY_PPI *SiPolicyPpiPreMem
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ ME_PEI_PREMEM_CONFIG *MePeiPreMemConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpiPreMem, &gMePeiPreMemConfigGuid, (VOID *) &MePeiPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "\n---------------------- Me Config Block Pre-Mem Print Begin -----------------\n"));
+ PrintMePeiPreMemConfig (MePeiPreMemConfig);
+ DEBUG ((DEBUG_INFO, "\n---------------------- Me Config Block Pre-Mem Print End -------------------\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Print PEI ME config block
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+MePrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ ME_PEI_CONFIG *MePeiConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gMePeiConfigGuid, (VOID *) &MePeiConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "\n---------------------- Me Config Block Print Begin -----------------\n"));
+ PrintMePeiConfig (MePeiConfig);
+ DEBUG ((DEBUG_INFO, "\n---------------------- Me Config Block Print End -------------------\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Get ME config block table total size.
+
+ @retval Size of ME config block table
+**/
+UINT16
+EFIAPI
+MeGetConfigBlockTotalSizePreMem (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mMeCompontBlockPreMemBlocks[0], sizeof (mMeCompontBlockPreMemBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ Get ME config block table total size.
+
+ @retval Size of ME config block table
+**/
+UINT16
+EFIAPI
+MeGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mMeCompontBlockBlocks[0], sizeof (mMeCompontBlockBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ MeAddConfigBlocksPreMem add all config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+MeAddConfigBlocksPreMem (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "Me AddConfigBlocks. TotalBlockCount = 0x%x\n", sizeof (mMeCompontBlockPreMemBlocks) / sizeof (COMPONENT_BLOCK_ENTRY)));
+
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mMeCompontBlockPreMemBlocks[0], sizeof (mMeCompontBlockPreMemBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ MeAddConfigBlocks add all config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+MeAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "ME AddConfigBlocks. TotalBlockCount = 0x%x\n", sizeof (mMeCompontBlockBlocks) / sizeof (COMPONENT_BLOCK_ENTRY)));
+
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mMeCompontBlockBlocks[0], sizeof (mMeCompontBlockBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.inf
new file mode 100644
index 0000000000..3c6e325772
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLib.inf
@@ -0,0 +1,52 @@
+## @file
+# Component description file for the PeiMePolicyLib libbrary.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiMePolicyLib
+FILE_GUID = 2655FA94-4559-F393-B0B1-85A8E79C1532
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PeiMePolicyLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+PeiServicesLib
+BaseMemoryLib
+MemoryAllocationLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiMePolicyLib.c
+PeiMePolicyLibrary.h
+
+
+[Ppis]
+gSiPolicyPpiGuid ## PRODUCES
+gSiPreMemPolicyPpiGuid ## PRODUCES
+
+
+[Guids]
+gMePeiPreMemConfigGuid
+gMePeiConfigGuid \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLibrary.h
new file mode 100644
index 0000000000..85e8e2b154
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Me/Library/PeiMePolicyLib/PeiMePolicyLibrary.h
@@ -0,0 +1,28 @@
+/** @file
+ Header file for the PeiMePolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_ME_POLICY_LIBRARY_H_
+#define _PEI_ME_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/PeiMePolicyLib.h>
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+
+#endif // _PEI_ME_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h
new file mode 100644
index 0000000000..9cde7e862d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h
@@ -0,0 +1,791 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+//
+// Definition for GPIO groups and pads
+//
+#ifndef GPIO_DEFINE_ASL
+#define GPIO_DEFINE_ASL
+
+#include "GpioPinsSklLp.h"
+#include "GpioPinsSklH.h"
+#include "Register/PchRegsGpio.h"
+
+//
+// SKL-PCH GPIO Community address
+//
+#define PCH_GPIO_COM0 0x00af0000 // PID_GPIOCOM0 = 0xAF
+#define PCH_GPIO_COM1 0x00ae0000 // PID_GPIOCOM1 = 0xAE
+#define PCH_GPIO_COM2 0x00ad0000 // PID_GPIOCOM2 = 0xAD
+#define PCH_GPIO_COM3 0x00ac0000 // PID_GPIOCOM3 = 0xAC
+
+//
+// SKL-PCH-LP GPIO pin list for driver usage
+//
+#define GPIO_SKL_LP_DRIVER_GPP_A_00 0
+#define GPIO_SKL_LP_DRIVER_GPP_A_01 1
+#define GPIO_SKL_LP_DRIVER_GPP_A_02 2
+#define GPIO_SKL_LP_DRIVER_GPP_A_03 3
+#define GPIO_SKL_LP_DRIVER_GPP_A_04 4
+#define GPIO_SKL_LP_DRIVER_GPP_A_05 5
+#define GPIO_SKL_LP_DRIVER_GPP_A_06 6
+#define GPIO_SKL_LP_DRIVER_GPP_A_07 7
+#define GPIO_SKL_LP_DRIVER_GPP_A_08 8
+#define GPIO_SKL_LP_DRIVER_GPP_A_09 9
+#define GPIO_SKL_LP_DRIVER_GPP_A_10 10
+#define GPIO_SKL_LP_DRIVER_GPP_A_11 11
+#define GPIO_SKL_LP_DRIVER_GPP_A_12 12
+#define GPIO_SKL_LP_DRIVER_GPP_A_13 13
+#define GPIO_SKL_LP_DRIVER_GPP_A_14 14
+#define GPIO_SKL_LP_DRIVER_GPP_A_15 15
+#define GPIO_SKL_LP_DRIVER_GPP_A_16 16
+#define GPIO_SKL_LP_DRIVER_GPP_A_17 17
+#define GPIO_SKL_LP_DRIVER_GPP_A_18 18
+#define GPIO_SKL_LP_DRIVER_GPP_A_19 19
+#define GPIO_SKL_LP_DRIVER_GPP_A_20 20
+#define GPIO_SKL_LP_DRIVER_GPP_A_21 21
+#define GPIO_SKL_LP_DRIVER_GPP_A_22 22
+#define GPIO_SKL_LP_DRIVER_GPP_A_23 23
+
+#define GPIO_SKL_LP_DRIVER_GPP_B_00 24
+#define GPIO_SKL_LP_DRIVER_GPP_B_01 25
+#define GPIO_SKL_LP_DRIVER_GPP_B_02 26
+#define GPIO_SKL_LP_DRIVER_GPP_B_03 27
+#define GPIO_SKL_LP_DRIVER_GPP_B_04 28
+#define GPIO_SKL_LP_DRIVER_GPP_B_05 29
+#define GPIO_SKL_LP_DRIVER_GPP_B_06 30
+#define GPIO_SKL_LP_DRIVER_GPP_B_07 31
+#define GPIO_SKL_LP_DRIVER_GPP_B_08 32
+#define GPIO_SKL_LP_DRIVER_GPP_B_09 33
+#define GPIO_SKL_LP_DRIVER_GPP_B_10 34
+#define GPIO_SKL_LP_DRIVER_GPP_B_11 35
+#define GPIO_SKL_LP_DRIVER_GPP_B_12 36
+#define GPIO_SKL_LP_DRIVER_GPP_B_13 37
+#define GPIO_SKL_LP_DRIVER_GPP_B_14 38
+#define GPIO_SKL_LP_DRIVER_GPP_B_15 39
+#define GPIO_SKL_LP_DRIVER_GPP_B_16 40
+#define GPIO_SKL_LP_DRIVER_GPP_B_17 41
+#define GPIO_SKL_LP_DRIVER_GPP_B_18 42
+#define GPIO_SKL_LP_DRIVER_GPP_B_19 43
+#define GPIO_SKL_LP_DRIVER_GPP_B_20 44
+#define GPIO_SKL_LP_DRIVER_GPP_B_21 45
+#define GPIO_SKL_LP_DRIVER_GPP_B_22 46
+#define GPIO_SKL_LP_DRIVER_GPP_B_23 47
+
+#define GPIO_SKL_LP_DRIVER_GPP_C_00 48
+#define GPIO_SKL_LP_DRIVER_GPP_C_01 49
+#define GPIO_SKL_LP_DRIVER_GPP_C_02 50
+#define GPIO_SKL_LP_DRIVER_GPP_C_03 51
+#define GPIO_SKL_LP_DRIVER_GPP_C_04 52
+#define GPIO_SKL_LP_DRIVER_GPP_C_05 53
+#define GPIO_SKL_LP_DRIVER_GPP_C_06 54
+#define GPIO_SKL_LP_DRIVER_GPP_C_07 55
+#define GPIO_SKL_LP_DRIVER_GPP_C_08 56
+#define GPIO_SKL_LP_DRIVER_GPP_C_09 57
+#define GPIO_SKL_LP_DRIVER_GPP_C_10 58
+#define GPIO_SKL_LP_DRIVER_GPP_C_11 59
+#define GPIO_SKL_LP_DRIVER_GPP_C_12 60
+#define GPIO_SKL_LP_DRIVER_GPP_C_13 61
+#define GPIO_SKL_LP_DRIVER_GPP_C_14 62
+#define GPIO_SKL_LP_DRIVER_GPP_C_15 63
+#define GPIO_SKL_LP_DRIVER_GPP_C_16 64
+#define GPIO_SKL_LP_DRIVER_GPP_C_17 65
+#define GPIO_SKL_LP_DRIVER_GPP_C_18 66
+#define GPIO_SKL_LP_DRIVER_GPP_C_19 67
+#define GPIO_SKL_LP_DRIVER_GPP_C_20 68
+#define GPIO_SKL_LP_DRIVER_GPP_C_21 69
+#define GPIO_SKL_LP_DRIVER_GPP_C_22 70
+#define GPIO_SKL_LP_DRIVER_GPP_C_23 71
+
+#define GPIO_SKL_LP_DRIVER_GPP_D_00 72
+#define GPIO_SKL_LP_DRIVER_GPP_D_01 73
+#define GPIO_SKL_LP_DRIVER_GPP_D_02 74
+#define GPIO_SKL_LP_DRIVER_GPP_D_03 75
+#define GPIO_SKL_LP_DRIVER_GPP_D_04 76
+#define GPIO_SKL_LP_DRIVER_GPP_D_05 77
+#define GPIO_SKL_LP_DRIVER_GPP_D_06 78
+#define GPIO_SKL_LP_DRIVER_GPP_D_07 79
+#define GPIO_SKL_LP_DRIVER_GPP_D_08 80
+#define GPIO_SKL_LP_DRIVER_GPP_D_09 81
+#define GPIO_SKL_LP_DRIVER_GPP_D_10 82
+#define GPIO_SKL_LP_DRIVER_GPP_D_11 83
+#define GPIO_SKL_LP_DRIVER_GPP_D_12 84
+#define GPIO_SKL_LP_DRIVER_GPP_D_13 85
+#define GPIO_SKL_LP_DRIVER_GPP_D_14 86
+#define GPIO_SKL_LP_DRIVER_GPP_D_15 87
+#define GPIO_SKL_LP_DRIVER_GPP_D_16 88
+#define GPIO_SKL_LP_DRIVER_GPP_D_17 89
+#define GPIO_SKL_LP_DRIVER_GPP_D_18 90
+#define GPIO_SKL_LP_DRIVER_GPP_D_19 91
+#define GPIO_SKL_LP_DRIVER_GPP_D_20 92
+#define GPIO_SKL_LP_DRIVER_GPP_D_21 93
+#define GPIO_SKL_LP_DRIVER_GPP_D_22 94
+#define GPIO_SKL_LP_DRIVER_GPP_D_23 95
+
+#define GPIO_SKL_LP_DRIVER_GPP_E_00 96
+#define GPIO_SKL_LP_DRIVER_GPP_E_01 97
+#define GPIO_SKL_LP_DRIVER_GPP_E_02 98
+#define GPIO_SKL_LP_DRIVER_GPP_E_03 99
+#define GPIO_SKL_LP_DRIVER_GPP_E_04 100
+#define GPIO_SKL_LP_DRIVER_GPP_E_05 101
+#define GPIO_SKL_LP_DRIVER_GPP_E_06 102
+#define GPIO_SKL_LP_DRIVER_GPP_E_07 103
+#define GPIO_SKL_LP_DRIVER_GPP_E_08 104
+#define GPIO_SKL_LP_DRIVER_GPP_E_09 105
+#define GPIO_SKL_LP_DRIVER_GPP_E_10 106
+#define GPIO_SKL_LP_DRIVER_GPP_E_11 107
+#define GPIO_SKL_LP_DRIVER_GPP_E_12 108
+#define GPIO_SKL_LP_DRIVER_GPP_E_13 109
+#define GPIO_SKL_LP_DRIVER_GPP_E_14 110
+#define GPIO_SKL_LP_DRIVER_GPP_E_15 111
+#define GPIO_SKL_LP_DRIVER_GPP_E_16 112
+#define GPIO_SKL_LP_DRIVER_GPP_E_17 113
+#define GPIO_SKL_LP_DRIVER_GPP_E_18 114
+#define GPIO_SKL_LP_DRIVER_GPP_E_19 115
+#define GPIO_SKL_LP_DRIVER_GPP_E_20 116
+#define GPIO_SKL_LP_DRIVER_GPP_E_21 117
+#define GPIO_SKL_LP_DRIVER_GPP_E_22 118
+#define GPIO_SKL_LP_DRIVER_GPP_E_23 119
+
+#define GPIO_SKL_LP_DRIVER_GPP_F_00 120
+#define GPIO_SKL_LP_DRIVER_GPP_F_01 121
+#define GPIO_SKL_LP_DRIVER_GPP_F_02 122
+#define GPIO_SKL_LP_DRIVER_GPP_F_03 123
+#define GPIO_SKL_LP_DRIVER_GPP_F_04 124
+#define GPIO_SKL_LP_DRIVER_GPP_F_05 125
+#define GPIO_SKL_LP_DRIVER_GPP_F_06 126
+#define GPIO_SKL_LP_DRIVER_GPP_F_07 127
+#define GPIO_SKL_LP_DRIVER_GPP_F_08 128
+#define GPIO_SKL_LP_DRIVER_GPP_F_09 129
+#define GPIO_SKL_LP_DRIVER_GPP_F_10 130
+#define GPIO_SKL_LP_DRIVER_GPP_F_11 131
+#define GPIO_SKL_LP_DRIVER_GPP_F_12 132
+#define GPIO_SKL_LP_DRIVER_GPP_F_13 133
+#define GPIO_SKL_LP_DRIVER_GPP_F_14 134
+#define GPIO_SKL_LP_DRIVER_GPP_F_15 135
+#define GPIO_SKL_LP_DRIVER_GPP_F_16 136
+#define GPIO_SKL_LP_DRIVER_GPP_F_17 137
+#define GPIO_SKL_LP_DRIVER_GPP_F_18 138
+#define GPIO_SKL_LP_DRIVER_GPP_F_19 139
+#define GPIO_SKL_LP_DRIVER_GPP_F_20 140
+#define GPIO_SKL_LP_DRIVER_GPP_F_21 141
+#define GPIO_SKL_LP_DRIVER_GPP_F_22 142
+#define GPIO_SKL_LP_DRIVER_GPP_F_23 143
+
+#define GPIO_SKL_LP_DRIVER_GPP_G_00 144
+#define GPIO_SKL_LP_DRIVER_GPP_G_01 145
+#define GPIO_SKL_LP_DRIVER_GPP_G_02 146
+#define GPIO_SKL_LP_DRIVER_GPP_G_03 147
+#define GPIO_SKL_LP_DRIVER_GPP_G_04 148
+#define GPIO_SKL_LP_DRIVER_GPP_G_05 149
+#define GPIO_SKL_LP_DRIVER_GPP_G_06 150
+#define GPIO_SKL_LP_DRIVER_GPP_G_07 151
+
+//
+// SPT H GPIO pin list for driver usage
+//
+#define GPIO_SKL_H_DRIVER_GPP_A_00 0
+#define GPIO_SKL_H_DRIVER_GPP_A_01 1
+#define GPIO_SKL_H_DRIVER_GPP_A_02 2
+#define GPIO_SKL_H_DRIVER_GPP_A_03 3
+#define GPIO_SKL_H_DRIVER_GPP_A_04 4
+#define GPIO_SKL_H_DRIVER_GPP_A_05 5
+#define GPIO_SKL_H_DRIVER_GPP_A_06 6
+#define GPIO_SKL_H_DRIVER_GPP_A_07 7
+#define GPIO_SKL_H_DRIVER_GPP_A_08 8
+#define GPIO_SKL_H_DRIVER_GPP_A_09 9
+#define GPIO_SKL_H_DRIVER_GPP_A_10 10
+#define GPIO_SKL_H_DRIVER_GPP_A_11 11
+#define GPIO_SKL_H_DRIVER_GPP_A_12 12
+#define GPIO_SKL_H_DRIVER_GPP_A_13 13
+#define GPIO_SKL_H_DRIVER_GPP_A_14 14
+#define GPIO_SKL_H_DRIVER_GPP_A_15 15
+#define GPIO_SKL_H_DRIVER_GPP_A_16 16
+#define GPIO_SKL_H_DRIVER_GPP_A_17 17
+#define GPIO_SKL_H_DRIVER_GPP_A_18 18
+#define GPIO_SKL_H_DRIVER_GPP_A_19 19
+#define GPIO_SKL_H_DRIVER_GPP_A_20 20
+#define GPIO_SKL_H_DRIVER_GPP_A_21 21
+#define GPIO_SKL_H_DRIVER_GPP_A_22 22
+#define GPIO_SKL_H_DRIVER_GPP_A_23 23
+
+#define GPIO_SKL_H_DRIVER_GPP_B_00 24
+#define GPIO_SKL_H_DRIVER_GPP_B_01 25
+#define GPIO_SKL_H_DRIVER_GPP_B_02 26
+#define GPIO_SKL_H_DRIVER_GPP_B_03 27
+#define GPIO_SKL_H_DRIVER_GPP_B_04 28
+#define GPIO_SKL_H_DRIVER_GPP_B_05 29
+#define GPIO_SKL_H_DRIVER_GPP_B_06 30
+#define GPIO_SKL_H_DRIVER_GPP_B_07 31
+#define GPIO_SKL_H_DRIVER_GPP_B_08 32
+#define GPIO_SKL_H_DRIVER_GPP_B_09 33
+#define GPIO_SKL_H_DRIVER_GPP_B_10 34
+#define GPIO_SKL_H_DRIVER_GPP_B_11 35
+#define GPIO_SKL_H_DRIVER_GPP_B_12 36
+#define GPIO_SKL_H_DRIVER_GPP_B_13 37
+#define GPIO_SKL_H_DRIVER_GPP_B_14 38
+#define GPIO_SKL_H_DRIVER_GPP_B_15 39
+#define GPIO_SKL_H_DRIVER_GPP_B_16 40
+#define GPIO_SKL_H_DRIVER_GPP_B_17 41
+#define GPIO_SKL_H_DRIVER_GPP_B_18 42
+#define GPIO_SKL_H_DRIVER_GPP_B_19 43
+#define GPIO_SKL_H_DRIVER_GPP_B_20 44
+#define GPIO_SKL_H_DRIVER_GPP_B_21 45
+#define GPIO_SKL_H_DRIVER_GPP_B_22 46
+#define GPIO_SKL_H_DRIVER_GPP_B_23 47
+
+#define GPIO_SKL_H_DRIVER_GPP_C_00 48
+#define GPIO_SKL_H_DRIVER_GPP_C_01 49
+#define GPIO_SKL_H_DRIVER_GPP_C_02 50
+#define GPIO_SKL_H_DRIVER_GPP_C_03 51
+#define GPIO_SKL_H_DRIVER_GPP_C_04 52
+#define GPIO_SKL_H_DRIVER_GPP_C_05 53
+#define GPIO_SKL_H_DRIVER_GPP_C_06 54
+#define GPIO_SKL_H_DRIVER_GPP_C_07 55
+#define GPIO_SKL_H_DRIVER_GPP_C_08 56
+#define GPIO_SKL_H_DRIVER_GPP_C_09 57
+#define GPIO_SKL_H_DRIVER_GPP_C_10 58
+#define GPIO_SKL_H_DRIVER_GPP_C_11 59
+#define GPIO_SKL_H_DRIVER_GPP_C_12 60
+#define GPIO_SKL_H_DRIVER_GPP_C_13 61
+#define GPIO_SKL_H_DRIVER_GPP_C_14 62
+#define GPIO_SKL_H_DRIVER_GPP_C_15 63
+#define GPIO_SKL_H_DRIVER_GPP_C_16 64
+#define GPIO_SKL_H_DRIVER_GPP_C_17 65
+#define GPIO_SKL_H_DRIVER_GPP_C_18 66
+#define GPIO_SKL_H_DRIVER_GPP_C_19 67
+#define GPIO_SKL_H_DRIVER_GPP_C_20 68
+#define GPIO_SKL_H_DRIVER_GPP_C_21 69
+#define GPIO_SKL_H_DRIVER_GPP_C_22 70
+#define GPIO_SKL_H_DRIVER_GPP_C_23 71
+
+#define GPIO_SKL_H_DRIVER_GPP_D_00 72
+#define GPIO_SKL_H_DRIVER_GPP_D_01 73
+#define GPIO_SKL_H_DRIVER_GPP_D_02 74
+#define GPIO_SKL_H_DRIVER_GPP_D_03 75
+#define GPIO_SKL_H_DRIVER_GPP_D_04 76
+#define GPIO_SKL_H_DRIVER_GPP_D_05 77
+#define GPIO_SKL_H_DRIVER_GPP_D_06 78
+#define GPIO_SKL_H_DRIVER_GPP_D_07 79
+#define GPIO_SKL_H_DRIVER_GPP_D_08 80
+#define GPIO_SKL_H_DRIVER_GPP_D_09 81
+#define GPIO_SKL_H_DRIVER_GPP_D_10 82
+#define GPIO_SKL_H_DRIVER_GPP_D_11 83
+#define GPIO_SKL_H_DRIVER_GPP_D_12 84
+#define GPIO_SKL_H_DRIVER_GPP_D_13 85
+#define GPIO_SKL_H_DRIVER_GPP_D_14 86
+#define GPIO_SKL_H_DRIVER_GPP_D_15 87
+#define GPIO_SKL_H_DRIVER_GPP_D_16 88
+#define GPIO_SKL_H_DRIVER_GPP_D_17 89
+#define GPIO_SKL_H_DRIVER_GPP_D_18 90
+#define GPIO_SKL_H_DRIVER_GPP_D_19 91
+#define GPIO_SKL_H_DRIVER_GPP_D_20 92
+#define GPIO_SKL_H_DRIVER_GPP_D_21 93
+#define GPIO_SKL_H_DRIVER_GPP_D_22 94
+#define GPIO_SKL_H_DRIVER_GPP_D_23 95
+
+#define GPIO_SKL_H_DRIVER_GPP_E_00 96
+#define GPIO_SKL_H_DRIVER_GPP_E_01 97
+#define GPIO_SKL_H_DRIVER_GPP_E_02 98
+#define GPIO_SKL_H_DRIVER_GPP_E_03 99
+#define GPIO_SKL_H_DRIVER_GPP_E_04 100
+#define GPIO_SKL_H_DRIVER_GPP_E_05 101
+#define GPIO_SKL_H_DRIVER_GPP_E_06 102
+#define GPIO_SKL_H_DRIVER_GPP_E_07 103
+#define GPIO_SKL_H_DRIVER_GPP_E_08 104
+#define GPIO_SKL_H_DRIVER_GPP_E_09 105
+#define GPIO_SKL_H_DRIVER_GPP_E_10 106
+#define GPIO_SKL_H_DRIVER_GPP_E_11 107
+#define GPIO_SKL_H_DRIVER_GPP_E_12 108
+#define GPIO_SKL_H_DRIVER_GPP_E_13 109
+
+#define GPIO_SKL_H_DRIVER_GPP_F_00 120
+#define GPIO_SKL_H_DRIVER_GPP_F_01 121
+#define GPIO_SKL_H_DRIVER_GPP_F_02 122
+#define GPIO_SKL_H_DRIVER_GPP_F_03 123
+#define GPIO_SKL_H_DRIVER_GPP_F_04 124
+#define GPIO_SKL_H_DRIVER_GPP_F_05 125
+#define GPIO_SKL_H_DRIVER_GPP_F_06 126
+#define GPIO_SKL_H_DRIVER_GPP_F_07 127
+#define GPIO_SKL_H_DRIVER_GPP_F_08 128
+#define GPIO_SKL_H_DRIVER_GPP_F_09 129
+#define GPIO_SKL_H_DRIVER_GPP_F_10 130
+#define GPIO_SKL_H_DRIVER_GPP_F_11 131
+#define GPIO_SKL_H_DRIVER_GPP_F_12 132
+#define GPIO_SKL_H_DRIVER_GPP_F_13 133
+#define GPIO_SKL_H_DRIVER_GPP_F_14 134
+#define GPIO_SKL_H_DRIVER_GPP_F_15 135
+#define GPIO_SKL_H_DRIVER_GPP_F_16 136
+#define GPIO_SKL_H_DRIVER_GPP_F_17 137
+#define GPIO_SKL_H_DRIVER_GPP_F_18 138
+#define GPIO_SKL_H_DRIVER_GPP_F_19 139
+#define GPIO_SKL_H_DRIVER_GPP_F_20 140
+#define GPIO_SKL_H_DRIVER_GPP_F_21 141
+#define GPIO_SKL_H_DRIVER_GPP_F_22 142
+#define GPIO_SKL_H_DRIVER_GPP_F_23 143
+
+#define GPIO_SKL_H_DRIVER_GPP_G_00 144
+#define GPIO_SKL_H_DRIVER_GPP_G_01 145
+#define GPIO_SKL_H_DRIVER_GPP_G_02 146
+#define GPIO_SKL_H_DRIVER_GPP_G_03 147
+#define GPIO_SKL_H_DRIVER_GPP_G_04 148
+#define GPIO_SKL_H_DRIVER_GPP_G_05 149
+#define GPIO_SKL_H_DRIVER_GPP_G_06 150
+#define GPIO_SKL_H_DRIVER_GPP_G_07 151
+#define GPIO_SKL_H_DRIVER_GPP_G_08 152
+#define GPIO_SKL_H_DRIVER_GPP_G_09 153
+#define GPIO_SKL_H_DRIVER_GPP_G_10 154
+#define GPIO_SKL_H_DRIVER_GPP_G_11 155
+#define GPIO_SKL_H_DRIVER_GPP_G_12 156
+#define GPIO_SKL_H_DRIVER_GPP_G_13 157
+#define GPIO_SKL_H_DRIVER_GPP_G_14 158
+#define GPIO_SKL_H_DRIVER_GPP_G_15 159
+#define GPIO_SKL_H_DRIVER_GPP_G_16 160
+#define GPIO_SKL_H_DRIVER_GPP_G_17 161
+#define GPIO_SKL_H_DRIVER_GPP_G_18 162
+#define GPIO_SKL_H_DRIVER_GPP_G_19 163
+#define GPIO_SKL_H_DRIVER_GPP_G_20 164
+#define GPIO_SKL_H_DRIVER_GPP_G_21 165
+#define GPIO_SKL_H_DRIVER_GPP_G_22 166
+#define GPIO_SKL_H_DRIVER_GPP_G_23 167
+
+#define GPIO_SKL_H_DRIVER_GPP_H_00 168
+#define GPIO_SKL_H_DRIVER_GPP_H_01 169
+#define GPIO_SKL_H_DRIVER_GPP_H_02 170
+#define GPIO_SKL_H_DRIVER_GPP_H_03 171
+#define GPIO_SKL_H_DRIVER_GPP_H_04 172
+#define GPIO_SKL_H_DRIVER_GPP_H_05 173
+#define GPIO_SKL_H_DRIVER_GPP_H_06 174
+#define GPIO_SKL_H_DRIVER_GPP_H_07 175
+#define GPIO_SKL_H_DRIVER_GPP_H_08 176
+#define GPIO_SKL_H_DRIVER_GPP_H_09 177
+#define GPIO_SKL_H_DRIVER_GPP_H_10 178
+#define GPIO_SKL_H_DRIVER_GPP_H_11 179
+#define GPIO_SKL_H_DRIVER_GPP_H_12 180
+#define GPIO_SKL_H_DRIVER_GPP_H_13 181
+#define GPIO_SKL_H_DRIVER_GPP_H_14 182
+#define GPIO_SKL_H_DRIVER_GPP_H_15 183
+#define GPIO_SKL_H_DRIVER_GPP_H_16 184
+#define GPIO_SKL_H_DRIVER_GPP_H_17 185
+#define GPIO_SKL_H_DRIVER_GPP_H_18 186
+#define GPIO_SKL_H_DRIVER_GPP_H_19 187
+#define GPIO_SKL_H_DRIVER_GPP_H_20 188
+#define GPIO_SKL_H_DRIVER_GPP_H_21 189
+#define GPIO_SKL_H_DRIVER_GPP_H_22 190
+#define GPIO_SKL_H_DRIVER_GPP_H_23 191
+
+#define PCH_I_GPIO_DRIVER_GPP_I_00 192
+#define PCH_I_GPIO_DRIVER_GPP_I_01 193
+#define PCH_I_GPIO_DRIVER_GPP_I_02 194
+#define PCH_I_GPIO_DRIVER_GPP_I_03 195
+#define PCH_I_GPIO_DRIVER_GPP_I_04 196
+#define PCH_I_GPIO_DRIVER_GPP_I_05 197
+#define PCH_I_GPIO_DRIVER_GPP_I_06 198
+#define PCH_I_GPIO_DRIVER_GPP_I_07 199
+#define PCH_I_GPIO_DRIVER_GPP_I_08 200
+#define PCH_I_GPIO_DRIVER_GPP_I_09 201
+#define PCH_I_GPIO_DRIVER_GPP_I_10 202
+
+//
+// SPT GPIO IOxAPIC interrupts
+//
+// SPT-LP:
+#define GPIO_SKL_LP_IOAPIC_GPP_A_00 0x18
+#define GPIO_SKL_LP_IOAPIC_GPP_A_01 0x19
+#define GPIO_SKL_LP_IOAPIC_GPP_A_02 0x1a
+#define GPIO_SKL_LP_IOAPIC_GPP_A_03 0x1b
+#define GPIO_SKL_LP_IOAPIC_GPP_A_04 0x1c
+#define GPIO_SKL_LP_IOAPIC_GPP_A_05 0x1d
+#define GPIO_SKL_LP_IOAPIC_GPP_A_06 0x1e
+#define GPIO_SKL_LP_IOAPIC_GPP_A_07 0x1f
+#define GPIO_SKL_LP_IOAPIC_GPP_A_08 0x20
+#define GPIO_SKL_LP_IOAPIC_GPP_A_09 0x21
+#define GPIO_SKL_LP_IOAPIC_GPP_A_10 0x22
+#define GPIO_SKL_LP_IOAPIC_GPP_A_11 0x23
+#define GPIO_SKL_LP_IOAPIC_GPP_A_12 0x24
+#define GPIO_SKL_LP_IOAPIC_GPP_A_13 0x25
+#define GPIO_SKL_LP_IOAPIC_GPP_A_14 0x26
+#define GPIO_SKL_LP_IOAPIC_GPP_A_15 0x27
+#define GPIO_SKL_LP_IOAPIC_GPP_A_16 0x28
+#define GPIO_SKL_LP_IOAPIC_GPP_A_17 0x29
+#define GPIO_SKL_LP_IOAPIC_GPP_A_18 0x2a
+#define GPIO_SKL_LP_IOAPIC_GPP_A_19 0x2b
+#define GPIO_SKL_LP_IOAPIC_GPP_A_20 0x2c
+#define GPIO_SKL_LP_IOAPIC_GPP_A_21 0x2d
+#define GPIO_SKL_LP_IOAPIC_GPP_A_22 0x2e
+#define GPIO_SKL_LP_IOAPIC_GPP_A_23 0x2f
+
+#define GPIO_SKL_LP_IOAPIC_GPP_B_00 0x30
+#define GPIO_SKL_LP_IOAPIC_GPP_B_01 0x31
+#define GPIO_SKL_LP_IOAPIC_GPP_B_02 0x32
+#define GPIO_SKL_LP_IOAPIC_GPP_B_03 0x33
+#define GPIO_SKL_LP_IOAPIC_GPP_B_04 0x34
+#define GPIO_SKL_LP_IOAPIC_GPP_B_05 0x35
+#define GPIO_SKL_LP_IOAPIC_GPP_B_06 0x36
+#define GPIO_SKL_LP_IOAPIC_GPP_B_07 0x37
+#define GPIO_SKL_LP_IOAPIC_GPP_B_08 0x38
+#define GPIO_SKL_LP_IOAPIC_GPP_B_09 0x39
+#define GPIO_SKL_LP_IOAPIC_GPP_B_10 0x3a
+#define GPIO_SKL_LP_IOAPIC_GPP_B_11 0x3b
+#define GPIO_SKL_LP_IOAPIC_GPP_B_12 0x3c
+#define GPIO_SKL_LP_IOAPIC_GPP_B_13 0x3d
+#define GPIO_SKL_LP_IOAPIC_GPP_B_14 0x3e
+#define GPIO_SKL_LP_IOAPIC_GPP_B_15 0x3f
+#define GPIO_SKL_LP_IOAPIC_GPP_B_16 0x40
+#define GPIO_SKL_LP_IOAPIC_GPP_B_17 0x41
+#define GPIO_SKL_LP_IOAPIC_GPP_B_18 0x42
+#define GPIO_SKL_LP_IOAPIC_GPP_B_19 0x43
+#define GPIO_SKL_LP_IOAPIC_GPP_B_20 0x44
+#define GPIO_SKL_LP_IOAPIC_GPP_B_21 0x45
+#define GPIO_SKL_LP_IOAPIC_GPP_B_22 0x46
+#define GPIO_SKL_LP_IOAPIC_GPP_B_23 0x47
+
+#define GPIO_SKL_LP_IOAPIC_GPP_C_00 0x48
+#define GPIO_SKL_LP_IOAPIC_GPP_C_01 0x49
+#define GPIO_SKL_LP_IOAPIC_GPP_C_02 0x4a
+#define GPIO_SKL_LP_IOAPIC_GPP_C_03 0x4b
+#define GPIO_SKL_LP_IOAPIC_GPP_C_04 0x4c
+#define GPIO_SKL_LP_IOAPIC_GPP_C_05 0x4d
+#define GPIO_SKL_LP_IOAPIC_GPP_C_06 0x4e
+#define GPIO_SKL_LP_IOAPIC_GPP_C_07 0x4f
+#define GPIO_SKL_LP_IOAPIC_GPP_C_08 0x50
+#define GPIO_SKL_LP_IOAPIC_GPP_C_09 0x51
+#define GPIO_SKL_LP_IOAPIC_GPP_C_10 0x52
+#define GPIO_SKL_LP_IOAPIC_GPP_C_11 0x53
+#define GPIO_SKL_LP_IOAPIC_GPP_C_12 0x54
+#define GPIO_SKL_LP_IOAPIC_GPP_C_13 0x55
+#define GPIO_SKL_LP_IOAPIC_GPP_C_14 0x56
+#define GPIO_SKL_LP_IOAPIC_GPP_C_15 0x57
+#define GPIO_SKL_LP_IOAPIC_GPP_C_16 0x58
+#define GPIO_SKL_LP_IOAPIC_GPP_C_17 0x59
+#define GPIO_SKL_LP_IOAPIC_GPP_C_18 0x5a
+#define GPIO_SKL_LP_IOAPIC_GPP_C_19 0x5b
+#define GPIO_SKL_LP_IOAPIC_GPP_C_20 0x5c
+#define GPIO_SKL_LP_IOAPIC_GPP_C_21 0x5d
+#define GPIO_SKL_LP_IOAPIC_GPP_C_22 0x5e
+#define GPIO_SKL_LP_IOAPIC_GPP_C_23 0x5f
+
+#define GPIO_SKL_LP_IOAPIC_GPP_D_00 0x60
+#define GPIO_SKL_LP_IOAPIC_GPP_D_01 0x61
+#define GPIO_SKL_LP_IOAPIC_GPP_D_02 0x62
+#define GPIO_SKL_LP_IOAPIC_GPP_D_03 0x63
+#define GPIO_SKL_LP_IOAPIC_GPP_D_04 0x64
+#define GPIO_SKL_LP_IOAPIC_GPP_D_05 0x65
+#define GPIO_SKL_LP_IOAPIC_GPP_D_06 0x66
+#define GPIO_SKL_LP_IOAPIC_GPP_D_07 0x67
+#define GPIO_SKL_LP_IOAPIC_GPP_D_08 0x68
+#define GPIO_SKL_LP_IOAPIC_GPP_D_09 0x69
+#define GPIO_SKL_LP_IOAPIC_GPP_D_10 0x6a
+#define GPIO_SKL_LP_IOAPIC_GPP_D_11 0x6b
+#define GPIO_SKL_LP_IOAPIC_GPP_D_12 0x6c
+#define GPIO_SKL_LP_IOAPIC_GPP_D_13 0x6d
+#define GPIO_SKL_LP_IOAPIC_GPP_D_14 0x6e
+#define GPIO_SKL_LP_IOAPIC_GPP_D_15 0x6f
+#define GPIO_SKL_LP_IOAPIC_GPP_D_16 0x70
+#define GPIO_SKL_LP_IOAPIC_GPP_D_17 0x71
+#define GPIO_SKL_LP_IOAPIC_GPP_D_18 0x72
+#define GPIO_SKL_LP_IOAPIC_GPP_D_19 0x73
+#define GPIO_SKL_LP_IOAPIC_GPP_D_20 0x74
+#define GPIO_SKL_LP_IOAPIC_GPP_D_21 0x75
+#define GPIO_SKL_LP_IOAPIC_GPP_D_22 0x76
+#define GPIO_SKL_LP_IOAPIC_GPP_D_23 0x77
+
+#define GPIO_SKL_LP_IOAPIC_GPP_E_00 0x18
+#define GPIO_SKL_LP_IOAPIC_GPP_E_01 0x19
+#define GPIO_SKL_LP_IOAPIC_GPP_E_02 0x1a
+#define GPIO_SKL_LP_IOAPIC_GPP_E_03 0x1b
+#define GPIO_SKL_LP_IOAPIC_GPP_E_04 0x1c
+#define GPIO_SKL_LP_IOAPIC_GPP_E_05 0x1d
+#define GPIO_SKL_LP_IOAPIC_GPP_E_06 0x1e
+#define GPIO_SKL_LP_IOAPIC_GPP_E_07 0x1f
+#define GPIO_SKL_LP_IOAPIC_GPP_E_08 0x20
+#define GPIO_SKL_LP_IOAPIC_GPP_E_09 0x21
+#define GPIO_SKL_LP_IOAPIC_GPP_E_10 0x22
+#define GPIO_SKL_LP_IOAPIC_GPP_E_11 0x23
+#define GPIO_SKL_LP_IOAPIC_GPP_E_12 0x24
+#define GPIO_SKL_LP_IOAPIC_GPP_E_13 0x25
+#define GPIO_SKL_LP_IOAPIC_GPP_E_14 0x26
+#define GPIO_SKL_LP_IOAPIC_GPP_E_15 0x27
+#define GPIO_SKL_LP_IOAPIC_GPP_E_16 0x28
+#define GPIO_SKL_LP_IOAPIC_GPP_E_17 0x29
+#define GPIO_SKL_LP_IOAPIC_GPP_E_18 0x2a
+#define GPIO_SKL_LP_IOAPIC_GPP_E_19 0x2b
+#define GPIO_SKL_LP_IOAPIC_GPP_E_20 0x2c
+#define GPIO_SKL_LP_IOAPIC_GPP_E_21 0x2d
+#define GPIO_SKL_LP_IOAPIC_GPP_E_22 0x2e
+#define GPIO_SKL_LP_IOAPIC_GPP_E_23 0x2f
+
+#define GPIO_SKL_LP_IOAPIC_GPP_F_00 0x30
+#define GPIO_SKL_LP_IOAPIC_GPP_F_01 0x31
+#define GPIO_SKL_LP_IOAPIC_GPP_F_02 0x32
+#define GPIO_SKL_LP_IOAPIC_GPP_F_03 0x33
+#define GPIO_SKL_LP_IOAPIC_GPP_F_04 0x34
+#define GPIO_SKL_LP_IOAPIC_GPP_F_05 0x35
+#define GPIO_SKL_LP_IOAPIC_GPP_F_06 0x36
+#define GPIO_SKL_LP_IOAPIC_GPP_F_07 0x37
+#define GPIO_SKL_LP_IOAPIC_GPP_F_08 0x38
+#define GPIO_SKL_LP_IOAPIC_GPP_F_09 0x39
+#define GPIO_SKL_LP_IOAPIC_GPP_F_10 0x3a
+#define GPIO_SKL_LP_IOAPIC_GPP_F_11 0x3b
+#define GPIO_SKL_LP_IOAPIC_GPP_F_12 0x3c
+#define GPIO_SKL_LP_IOAPIC_GPP_F_13 0x3d
+#define GPIO_SKL_LP_IOAPIC_GPP_F_14 0x3e
+#define GPIO_SKL_LP_IOAPIC_GPP_F_15 0x3f
+#define GPIO_SKL_LP_IOAPIC_GPP_F_16 0x40
+#define GPIO_SKL_LP_IOAPIC_GPP_F_17 0x41
+#define GPIO_SKL_LP_IOAPIC_GPP_F_18 0x42
+#define GPIO_SKL_LP_IOAPIC_GPP_F_19 0x43
+#define GPIO_SKL_LP_IOAPIC_GPP_F_20 0x44
+#define GPIO_SKL_LP_IOAPIC_GPP_F_21 0x45
+#define GPIO_SKL_LP_IOAPIC_GPP_F_22 0x46
+#define GPIO_SKL_LP_IOAPIC_GPP_F_23 0x47
+
+#define GPIO_SKL_LP_IOAPIC_GPP_G_00 0x48
+#define GPIO_SKL_LP_IOAPIC_GPP_G_01 0x49
+#define GPIO_SKL_LP_IOAPIC_GPP_G_02 0x4a
+#define GPIO_SKL_LP_IOAPIC_GPP_G_03 0x4b
+#define GPIO_SKL_LP_IOAPIC_GPP_G_04 0x4c
+#define GPIO_SKL_LP_IOAPIC_GPP_G_05 0x4d
+#define GPIO_SKL_LP_IOAPIC_GPP_G_06 0x4e
+#define GPIO_SKL_LP_IOAPIC_GPP_G_07 0x4f
+
+#define GPIO_SKL_LP_IOAPIC_GPD_00 0x50
+#define GPIO_SKL_LP_IOAPIC_GPD_01 0x51
+#define GPIO_SKL_LP_IOAPIC_GPD_02 0x52
+#define GPIO_SKL_LP_IOAPIC_GPD_03 0x53
+#define GPIO_SKL_LP_IOAPIC_GPD_04 0x54
+#define GPIO_SKL_LP_IOAPIC_GPD_05 0x55
+#define GPIO_SKL_LP_IOAPIC_GPD_06 0x56
+#define GPIO_SKL_LP_IOAPIC_GPD_07 0x57
+#define GPIO_SKL_LP_IOAPIC_GPD_08 0x58
+#define GPIO_SKL_LP_IOAPIC_GPD_09 0x59
+#define GPIO_SKL_LP_IOAPIC_GPD_10 0x5a
+#define GPIO_SKL_LP_IOAPIC_GPD_11 0x5b
+
+//SPT-H:
+#define GPIO_SKL_H_IOAPIC_GPP_A_00 0x18
+#define GPIO_SKL_H_IOAPIC_GPP_A_01 0x19
+#define GPIO_SKL_H_IOAPIC_GPP_A_02 0x1a
+#define GPIO_SKL_H_IOAPIC_GPP_A_03 0x1b
+#define GPIO_SKL_H_IOAPIC_GPP_A_04 0x1c
+#define GPIO_SKL_H_IOAPIC_GPP_A_05 0x1d
+#define GPIO_SKL_H_IOAPIC_GPP_A_06 0x1e
+#define GPIO_SKL_H_IOAPIC_GPP_A_07 0x1f
+#define GPIO_SKL_H_IOAPIC_GPP_A_08 0x20
+#define GPIO_SKL_H_IOAPIC_GPP_A_09 0x21
+#define GPIO_SKL_H_IOAPIC_GPP_A_10 0x22
+#define GPIO_SKL_H_IOAPIC_GPP_A_11 0x23
+#define GPIO_SKL_H_IOAPIC_GPP_A_12 0x24
+#define GPIO_SKL_H_IOAPIC_GPP_A_13 0x25
+#define GPIO_SKL_H_IOAPIC_GPP_A_14 0x26
+#define GPIO_SKL_H_IOAPIC_GPP_A_15 0x27
+#define GPIO_SKL_H_IOAPIC_GPP_A_16 0x28
+#define GPIO_SKL_H_IOAPIC_GPP_A_17 0x29
+#define GPIO_SKL_H_IOAPIC_GPP_A_18 0x2a
+#define GPIO_SKL_H_IOAPIC_GPP_A_19 0x2b
+#define GPIO_SKL_H_IOAPIC_GPP_A_20 0x2c
+#define GPIO_SKL_H_IOAPIC_GPP_A_21 0x2d
+#define GPIO_SKL_H_IOAPIC_GPP_A_22 0x2e
+#define GPIO_SKL_H_IOAPIC_GPP_A_23 0x2f
+
+#define GPIO_SKL_H_IOAPIC_GPP_B_00 0x30
+#define GPIO_SKL_H_IOAPIC_GPP_B_01 0x31
+#define GPIO_SKL_H_IOAPIC_GPP_B_02 0x32
+#define GPIO_SKL_H_IOAPIC_GPP_B_03 0x33
+#define GPIO_SKL_H_IOAPIC_GPP_B_04 0x34
+#define GPIO_SKL_H_IOAPIC_GPP_B_05 0x35
+#define GPIO_SKL_H_IOAPIC_GPP_B_06 0x36
+#define GPIO_SKL_H_IOAPIC_GPP_B_07 0x37
+#define GPIO_SKL_H_IOAPIC_GPP_B_08 0x38
+#define GPIO_SKL_H_IOAPIC_GPP_B_09 0x39
+#define GPIO_SKL_H_IOAPIC_GPP_B_10 0x3a
+#define GPIO_SKL_H_IOAPIC_GPP_B_11 0x3b
+#define GPIO_SKL_H_IOAPIC_GPP_B_12 0x3c
+#define GPIO_SKL_H_IOAPIC_GPP_B_13 0x3d
+#define GPIO_SKL_H_IOAPIC_GPP_B_14 0x3e
+#define GPIO_SKL_H_IOAPIC_GPP_B_15 0x3f
+#define GPIO_SKL_H_IOAPIC_GPP_B_16 0x40
+#define GPIO_SKL_H_IOAPIC_GPP_B_17 0x41
+#define GPIO_SKL_H_IOAPIC_GPP_B_18 0x42
+#define GPIO_SKL_H_IOAPIC_GPP_B_19 0x43
+#define GPIO_SKL_H_IOAPIC_GPP_B_20 0x44
+#define GPIO_SKL_H_IOAPIC_GPP_B_21 0x45
+#define GPIO_SKL_H_IOAPIC_GPP_B_22 0x46
+#define GPIO_SKL_H_IOAPIC_GPP_B_23 0x47
+
+#define GPIO_SKL_H_IOAPIC_GPP_C_00 0x48
+#define GPIO_SKL_H_IOAPIC_GPP_C_01 0x49
+#define GPIO_SKL_H_IOAPIC_GPP_C_02 0x4a
+#define GPIO_SKL_H_IOAPIC_GPP_C_03 0x4b
+#define GPIO_SKL_H_IOAPIC_GPP_C_04 0x4c
+#define GPIO_SKL_H_IOAPIC_GPP_C_05 0x4d
+#define GPIO_SKL_H_IOAPIC_GPP_C_06 0x4e
+#define GPIO_SKL_H_IOAPIC_GPP_C_07 0x4f
+#define GPIO_SKL_H_IOAPIC_GPP_C_08 0x50
+#define GPIO_SKL_H_IOAPIC_GPP_C_09 0x51
+#define GPIO_SKL_H_IOAPIC_GPP_C_10 0x52
+#define GPIO_SKL_H_IOAPIC_GPP_C_11 0x53
+#define GPIO_SKL_H_IOAPIC_GPP_C_12 0x54
+#define GPIO_SKL_H_IOAPIC_GPP_C_13 0x55
+#define GPIO_SKL_H_IOAPIC_GPP_C_14 0x56
+#define GPIO_SKL_H_IOAPIC_GPP_C_15 0x57
+#define GPIO_SKL_H_IOAPIC_GPP_C_16 0x58
+#define GPIO_SKL_H_IOAPIC_GPP_C_17 0x59
+#define GPIO_SKL_H_IOAPIC_GPP_C_18 0x5a
+#define GPIO_SKL_H_IOAPIC_GPP_C_19 0x5b
+#define GPIO_SKL_H_IOAPIC_GPP_C_20 0x5c
+#define GPIO_SKL_H_IOAPIC_GPP_C_21 0x5d
+#define GPIO_SKL_H_IOAPIC_GPP_C_22 0x5e
+#define GPIO_SKL_H_IOAPIC_GPP_C_23 0x5f
+
+#define GPIO_SKL_H_IOAPIC_GPP_D_00 0x60
+#define GPIO_SKL_H_IOAPIC_GPP_D_01 0x61
+#define GPIO_SKL_H_IOAPIC_GPP_D_02 0x62
+#define GPIO_SKL_H_IOAPIC_GPP_D_03 0x63
+#define GPIO_SKL_H_IOAPIC_GPP_D_04 0x64
+#define GPIO_SKL_H_IOAPIC_GPP_D_05 0x65
+#define GPIO_SKL_H_IOAPIC_GPP_D_06 0x66
+#define GPIO_SKL_H_IOAPIC_GPP_D_07 0x67
+#define GPIO_SKL_H_IOAPIC_GPP_D_08 0x68
+#define GPIO_SKL_H_IOAPIC_GPP_D_09 0x69
+#define GPIO_SKL_H_IOAPIC_GPP_D_10 0x6a
+#define GPIO_SKL_H_IOAPIC_GPP_D_11 0x6b
+#define GPIO_SKL_H_IOAPIC_GPP_D_12 0x6c
+#define GPIO_SKL_H_IOAPIC_GPP_D_13 0x6d
+#define GPIO_SKL_H_IOAPIC_GPP_D_14 0x6e
+#define GPIO_SKL_H_IOAPIC_GPP_D_15 0x6f
+#define GPIO_SKL_H_IOAPIC_GPP_D_16 0x70
+#define GPIO_SKL_H_IOAPIC_GPP_D_17 0x71
+#define GPIO_SKL_H_IOAPIC_GPP_D_18 0x72
+#define GPIO_SKL_H_IOAPIC_GPP_D_19 0x73
+#define GPIO_SKL_H_IOAPIC_GPP_D_20 0x74
+#define GPIO_SKL_H_IOAPIC_GPP_D_21 0x75
+#define GPIO_SKL_H_IOAPIC_GPP_D_22 0x76
+#define GPIO_SKL_H_IOAPIC_GPP_D_23 0x77
+
+#define GPIO_SKL_H_IOAPIC_GPP_E_00 0x18
+#define GPIO_SKL_H_IOAPIC_GPP_E_01 0x19
+#define GPIO_SKL_H_IOAPIC_GPP_E_02 0x1a
+#define GPIO_SKL_H_IOAPIC_GPP_E_03 0x1b
+#define GPIO_SKL_H_IOAPIC_GPP_E_04 0x1c
+#define GPIO_SKL_H_IOAPIC_GPP_E_05 0x1d
+#define GPIO_SKL_H_IOAPIC_GPP_E_06 0x1e
+#define GPIO_SKL_H_IOAPIC_GPP_E_07 0x1f
+#define GPIO_SKL_H_IOAPIC_GPP_E_08 0x20
+#define GPIO_SKL_H_IOAPIC_GPP_E_09 0x21
+#define GPIO_SKL_H_IOAPIC_GPP_E_10 0x22
+#define GPIO_SKL_H_IOAPIC_GPP_E_11 0x23
+#define GPIO_SKL_H_IOAPIC_GPP_E_12 0x24
+
+#define GPIO_SKL_H_IOAPIC_GPP_F_00 0x25
+#define GPIO_SKL_H_IOAPIC_GPP_F_01 0x26
+#define GPIO_SKL_H_IOAPIC_GPP_F_02 0x27
+#define GPIO_SKL_H_IOAPIC_GPP_F_03 0x28
+#define GPIO_SKL_H_IOAPIC_GPP_F_04 0x29
+#define GPIO_SKL_H_IOAPIC_GPP_F_05 0x2a
+#define GPIO_SKL_H_IOAPIC_GPP_F_06 0x2b
+#define GPIO_SKL_H_IOAPIC_GPP_F_07 0x2c
+#define GPIO_SKL_H_IOAPIC_GPP_F_08 0x2d
+#define GPIO_SKL_H_IOAPIC_GPP_F_09 0x2e
+#define GPIO_SKL_H_IOAPIC_GPP_F_10 0x2f
+#define GPIO_SKL_H_IOAPIC_GPP_F_11 0x30
+#define GPIO_SKL_H_IOAPIC_GPP_F_12 0x31
+#define GPIO_SKL_H_IOAPIC_GPP_F_13 0x32
+#define GPIO_SKL_H_IOAPIC_GPP_F_14 0x33
+#define GPIO_SKL_H_IOAPIC_GPP_F_15 0x34
+#define GPIO_SKL_H_IOAPIC_GPP_F_16 0x35
+#define GPIO_SKL_H_IOAPIC_GPP_F_17 0x36
+#define GPIO_SKL_H_IOAPIC_GPP_F_18 0x37
+#define GPIO_SKL_H_IOAPIC_GPP_F_19 0x38
+#define GPIO_SKL_H_IOAPIC_GPP_F_20 0x39
+#define GPIO_SKL_H_IOAPIC_GPP_F_21 0x3a
+#define GPIO_SKL_H_IOAPIC_GPP_F_22 0x3b
+#define GPIO_SKL_H_IOAPIC_GPP_F_23 0x3c
+
+#define GPIO_SKL_H_IOAPIC_GPP_G_00 0x3d
+#define GPIO_SKL_H_IOAPIC_GPP_G_01 0x3e
+#define GPIO_SKL_H_IOAPIC_GPP_G_02 0x3f
+#define GPIO_SKL_H_IOAPIC_GPP_G_03 0x40
+#define GPIO_SKL_H_IOAPIC_GPP_G_04 0x41
+#define GPIO_SKL_H_IOAPIC_GPP_G_05 0x42
+#define GPIO_SKL_H_IOAPIC_GPP_G_06 0x43
+#define GPIO_SKL_H_IOAPIC_GPP_G_07 0x44
+#define GPIO_SKL_H_IOAPIC_GPP_G_08 0x45
+#define GPIO_SKL_H_IOAPIC_GPP_G_09 0x46
+#define GPIO_SKL_H_IOAPIC_GPP_G_10 0x47
+#define GPIO_SKL_H_IOAPIC_GPP_G_11 0x48
+#define GPIO_SKL_H_IOAPIC_GPP_G_12 0x49
+#define GPIO_SKL_H_IOAPIC_GPP_G_13 0x4a
+#define GPIO_SKL_H_IOAPIC_GPP_G_14 0x4b
+#define GPIO_SKL_H_IOAPIC_GPP_G_15 0x4c
+#define GPIO_SKL_H_IOAPIC_GPP_G_16 0x4d
+#define GPIO_SKL_H_IOAPIC_GPP_G_17 0x4e
+#define GPIO_SKL_H_IOAPIC_GPP_G_18 0x4f
+#define GPIO_SKL_H_IOAPIC_GPP_G_19 0x50
+#define GPIO_SKL_H_IOAPIC_GPP_G_20 0x51
+#define GPIO_SKL_H_IOAPIC_GPP_G_21 0x52
+#define GPIO_SKL_H_IOAPIC_GPP_G_22 0x53
+#define GPIO_SKL_H_IOAPIC_GPP_G_23 0x54
+
+#define GPIO_SKL_H_IOAPIC_GPP_H_00 0x55
+#define GPIO_SKL_H_IOAPIC_GPP_H_01 0x56
+#define GPIO_SKL_H_IOAPIC_GPP_H_02 0x57
+#define GPIO_SKL_H_IOAPIC_GPP_H_03 0x58
+#define GPIO_SKL_H_IOAPIC_GPP_H_04 0x59
+#define GPIO_SKL_H_IOAPIC_GPP_H_05 0x5a
+#define GPIO_SKL_H_IOAPIC_GPP_H_06 0x5b
+#define GPIO_SKL_H_IOAPIC_GPP_H_07 0x5c
+#define GPIO_SKL_H_IOAPIC_GPP_H_08 0x5d
+#define GPIO_SKL_H_IOAPIC_GPP_H_09 0x5e
+#define GPIO_SKL_H_IOAPIC_GPP_H_10 0x5f
+#define GPIO_SKL_H_IOAPIC_GPP_H_11 0x60
+#define GPIO_SKL_H_IOAPIC_GPP_H_12 0x61
+#define GPIO_SKL_H_IOAPIC_GPP_H_13 0x62
+#define GPIO_SKL_H_IOAPIC_GPP_H_14 0x63
+#define GPIO_SKL_H_IOAPIC_GPP_H_15 0x64
+#define GPIO_SKL_H_IOAPIC_GPP_H_16 0x65
+#define GPIO_SKL_H_IOAPIC_GPP_H_17 0x66
+#define GPIO_SKL_H_IOAPIC_GPP_H_18 0x67
+#define GPIO_SKL_H_IOAPIC_GPP_H_19 0x68
+#define GPIO_SKL_H_IOAPIC_GPP_H_20 0x69
+#define GPIO_SKL_H_IOAPIC_GPP_H_21 0x6a
+#define GPIO_SKL_H_IOAPIC_GPP_H_22 0x6b
+#define GPIO_SKL_H_IOAPIC_GPP_H_23 0x6c
+
+#define GPIO_SKL_H_IOAPIC_GPP_I_00 0x6d
+#define GPIO_SKL_H_IOAPIC_GPP_I_01 0x6e
+#define GPIO_SKL_H_IOAPIC_GPP_I_02 0x6f
+#define GPIO_SKL_H_IOAPIC_GPP_I_03 0x70
+#define GPIO_SKL_H_IOAPIC_GPP_I_04 0x71
+#define GPIO_SKL_H_IOAPIC_GPP_I_05 0x72
+#define GPIO_SKL_H_IOAPIC_GPP_I_06 0x73
+#define GPIO_SKL_H_IOAPIC_GPP_I_07 0x74
+#define GPIO_SKL_H_IOAPIC_GPP_I_08 0x75
+#define GPIO_SKL_H_IOAPIC_GPP_I_09 0x76
+#define GPIO_SKL_H_IOAPIC_GPP_I_10 0x77
+
+#define GPIO_SKL_H_IOAPIC_GPD_00 0x18
+#define GPIO_SKL_H_IOAPIC_GPD_01 0x19
+#define GPIO_SKL_H_IOAPIC_GPD_02 0x1a
+#define GPIO_SKL_H_IOAPIC_GPD_03 0x1b
+#define GPIO_SKL_H_IOAPIC_GPD_04 0x1c
+#define GPIO_SKL_H_IOAPIC_GPD_05 0x1d
+#define GPIO_SKL_H_IOAPIC_GPD_06 0x1e
+#define GPIO_SKL_H_IOAPIC_GPD_07 0x1f
+#define GPIO_SKL_H_IOAPIC_GPD_08 0x20
+#define GPIO_SKL_H_IOAPIC_GPD_09 0x21
+#define GPIO_SKL_H_IOAPIC_GPD_10 0x22
+#define GPIO_SKL_H_IOAPIC_GPD_11 0x23
+
+#endif // GPIO_DEFINE_ASL
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl
new file mode 100644
index 0000000000..b9809bd2ab
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl
@@ -0,0 +1,849 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+include("GpioLibObjects.asl")
+
+//
+// PADCFG register is split into multiple DW registers
+// PAD_CFG_SIZE holds number of bytes used by all those registers for one pad
+//
+#define PAD_CFG_SIZE 0x08
+
+//
+// Get number of DoubleWord registers used by one group
+//
+#define TOTAL_NUMBER_OF_DW_REGS_FOR_GPIO_GROUP(GpioGroupIndex) \
+ ( \
+ Add( \
+ ShiftRight( \
+ GINF(GpioGroupIndex,GPIO_PAD_NUM_FIELD), \
+ 5), \
+ 1) \
+ )
+
+//
+// Check if group belongs to 2-Tier GPE
+//
+#define IS_GPIO_GROUP_IN_2_TIER_GPE(GpioGroupIndex) \
+ ( \
+ LEqual( \
+ And( \
+ ShiftRight( \
+ GPEM, \
+ Multiply( \
+ GpioGroupIndex, \
+ 2)), \
+ 0x3), \
+ 0x0) \
+ )
+
+//
+// Get PADCFG_DW0 GpioPad register address
+//
+#define GET_GPIO_PAD_PADCFG_REG_ADDRESS(GpioGroupIndex,GpioPadNumber) \
+ ( \
+ Add( \
+ GET_PADCFG_REG_ADDRESS(GpioGroupIndex), \
+ Multiply( \
+ GpioPadNumber, \
+ PAD_CFG_SIZE) \
+ ) \
+ )
+
+//
+// Get GPIO register address
+// If group has more DW registers for certain feature
+// below macro will return address of the first one.
+//
+#define GET_PADCFG_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_PADCFG_REG_FIELD)
+#define GET_HOSTSW_OWN_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_HOSTOWN_REG_FIELD)
+#define GET_PAD_OWN_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_PADOWN_REG_FIELD)
+#define GET_GPE_STS_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_GPE_STS_REG_FIELD)
+
+//
+// GPIO Access Library
+//
+Scope(\_SB)
+{
+ //
+ // Arg1 possible values for internal GINF function
+ //
+ #define GPIO_COM_FIELD 0
+ #define GPIO_PAD_NUM_FIELD 1
+ #define GPIO_PADCFG_REG_FIELD 2
+ #define GPIO_HOSTOWN_REG_FIELD 3
+ #define GPIO_PADOWN_REG_FIELD 4
+ #define GPIO_GPE_STS_REG_FIELD 5
+
+ //
+ // Get GPIO group information
+ // This is internal library function
+ //
+ Method(GINF, 0x2, NotSerialized)
+ {
+ //
+ // Arg0 - GPIO Group index
+ // Arg1 - GPIO field type
+ //
+ If(LEqual(PCHS, SPTL)) { // PCH-LP
+ Return (PCH_LP_GPIO_GET_FIELD(Arg0,Arg1))
+ } Else { //PCH-H
+ Return (PCH_H_GPIO_GET_FIELD(Arg0,Arg1))
+ }
+ }
+
+ //
+ // Get GPIO maximal group
+ // This is internal library function
+ //
+ Method(GMXG, 0x0, NotSerialized)
+ {
+ If(LEqual(PCHS, SPTL)) { // PCH-LP
+ Return (V_PCH_LP_GPIO_GROUP_MAX)
+ } Else { //PCH-H
+ Return (V_PCH_H_GPIO_GROUP_MAX)
+ }
+ }
+
+ //
+ // Get GPIO register address
+ // This is internal library function
+ //
+ Method(GADR, 0x2, NotSerialized)
+ {
+ //
+ // Arg0 - GPIO Group index
+ // Arg1 - GPIO register type, must match what is used by GINF method
+ //
+ //Local0 = GpioCommunityAddress
+ Store( Add(GINF(Arg0,GPIO_COM_FIELD), SBRG), Local0)
+
+ //Local1 = Register Offset
+ Store(GINF(Arg0,Arg1), Local1)
+
+ Return( Add (Local0, Local1))
+ }
+
+ //
+ // Get GPIO absolute number for selected GpioPad
+ //
+ Method(GNUM, 0x1, NotSerialized)
+ {
+ //
+ // Arg0 - GpioPad
+ //
+
+ // Local0 - Gpio pad number
+ Store (GNMB(Arg0), Local0)
+ // Local1 - Gpio group index for GpioPad
+ Store (GGRP(Arg0), Local1)
+
+ Return (Add(Local0,Multiply(Local1, 24)))
+ }
+
+ //
+ // Get interrupt number for selected GpioPad
+ //
+ Method(INUM, 0x1, NotSerialized)
+ {
+ //
+ // Arg0 - GpioPad
+ //
+ // Local1 - Gpio pad number
+ Store (GNMB(Arg0), Local1)
+ // Local2 - Gpio group index for GpioPad
+ Store (GGRP(Arg0), Local2)
+ // Local3 - Group index used in a loop
+ Store (0 , Local3)
+
+ While(LLess (Local3, Local2)) {
+ // Get Number of GpioPads for certain Group (GroupIndex - Local3) and add it to Local1
+ Add( GINF(Local3,GPIO_PAD_NUM_FIELD) ,Local1,Local1)
+
+ Increment(Local3)
+ }
+
+ return(Add(24,Mod(Local1,96)))
+ }
+
+ //
+ // Get GPIO group index for GpioPad
+ //
+ Method(GGRP,1,serialized) {
+ //
+ // Arg0 - GpioPad
+ //
+ ShiftRight( And(Arg0,0x00FF0000), 16, Local0)
+ return (Local0)
+ }
+
+ //
+ // Get GPIO pin number for GpioPad
+ //
+ Method(GNMB,1,serialized) {
+ //
+ // Arg0 - GpioPad
+ //
+ return (And(Arg0,0x0000FFFF))
+ }
+
+ //
+ // GPEM (part of PCH NVS) is an object for informing how GPIO groups are mapped to GPE.
+ // Mapping for GPP_x is evaluated from (GPEM >> (GroupNumber*2)) & 0x3
+ // Possible values for each group:
+ // 00b - 2-tier
+ // 01b - 1-tier, GPE_DW0
+ // 10b - 1-tier, GPE_DW1
+ // 11b - 1-tier, GPE_DW2
+ //
+
+ //
+ // Get GPE number for selected GpioPad
+ //
+ Method(GGPE, 0x1, NotSerialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+
+ //Local0 - GPIO group index (GPP_A - 0, GPP_B - 1 ... )
+ Store (GGRP(Arg0), Local0)
+ //Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ If (IS_GPIO_GROUP_IN_2_TIER_GPE(Local0)) {
+ //
+ // Pads mapped to 2-tier GPE will all generate GPE_111
+ //
+ Return (0x6F)
+ } Else {
+ //
+ // Get mapping for certain group
+ // Local2 = (GPEM >> (Local0*2)) & 0x3
+ //
+ Store(And(ShiftRight(GPEM,Multiply(Local0,2)),0x3),Local2)
+ //
+ // For 1-tier GPE calculate GPE number
+ // GPE number = (Local2 - 1)*32 + Local1
+ //
+ Return (Add(Multiply(Subtract(Local2,1),32),Local1))
+ }
+ }
+
+ //
+ // Get Pad Configuration DW0 register value
+ //
+ Method(GPC0, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store(GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set Pad Configuration DW0 register value
+ //
+ Method(SPC0, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for DW0 register
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get Pad Configuration DW1 register value
+ //
+ Method(GPC1, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE) + 0x4
+ Store( Add( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),0x4),Local2)
+ OperationRegion(PDW1, SystemMemory, Local2, 4)
+ Field(PDW1, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set Pad Configuration DW1 register value
+ //
+ Method(SPC1, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for DW1 register
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local0 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE) + 0x4
+ Store( Add( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),0x4),Local2)
+ OperationRegion(PDW1, SystemMemory, Local2, 4)
+ Field(PDW1, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Set RX Override
+ //
+ Method(SRXO, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - 0=no override, 1=drive RX to 1 internally
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ ,28,
+ TEMP,1,
+ ,3
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPI Input Value
+ //
+ Method(GGIV, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 1,
+ TEMP,1,
+ , 30
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Get GPO Output Value
+ //
+ Method(GGOV, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,1,
+ , 31
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set GPO Output Value
+ //
+ Method(SGOV, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value of GPIO Tx State
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,1,
+ , 31
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPI Input Invert Bit
+ //
+ Method(GGII, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 23,
+ TEMP,1,
+ , 8
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set GPI Input Invert Bit
+ //
+ Method(SGII, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value of RXINV bit for selected pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 23,
+ TEMP,1,
+ , 8
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPIO Pad Mode
+ //
+ Method(GPMV, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 10,
+ TEMP,3,
+ , 19
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set GPIO Pad Mode
+ //
+ Method(SPMV, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for Pad Mode for selected pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 10,
+ TEMP,3,
+ , 19
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPIO Host Software Pad Ownership
+ //
+ Method(GHPO, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local3 - Register offset = HostSwOwnRegOffset + (GpioPadNumber >> 5)*0x4
+ Add (GET_HOSTSW_OWN_REG_ADDRESS(Local0), Multiply (ShiftRight(Local1,5), 0x4), Local3)
+ // Local4 - Pad bit position within register, Local4 = GpioPad & 0x1F = GpioPad % 32
+ And (Local1, 0x1F, Local4)
+
+ OperationRegion(PREG, SystemMemory, Local3, 4)
+ Field(PREG, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ // HostSwOwnValue = (TEMP >> Local4) & 0x1
+ Return( And( ShiftRight(TEMP,Local4),0x1))
+ }
+
+ //
+ // Set GPIO Host Software Pad Ownership
+ //
+ Method(SHPO, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for GPIO Host Software Pad Ownership
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local3 - Register offset = HostSwOwnRegOffset + (GpioPadNumber >> 5)*0x4
+ Add (GET_HOSTSW_OWN_REG_ADDRESS(Local0), Multiply (ShiftRight(Local1,5), 0x4), Local3)
+ // Local4 - Pad bit position within register, Local4 = GpioPad & 0x1F = GpioPad % 32
+ And (Local1, 0x1F, Local4)
+
+ OperationRegion(PREG, SystemMemory, Local3, 4)
+ Field(PREG, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+
+ If (Arg1) {
+ //TEMP = TEMP | (1 << PadBitPosition)
+ Or(TEMP, ShiftLeft(1,Local4), TEMP)
+ } Else {
+ //TEMP = TEMP & ~(1 << PadBitPosition)
+ And(TEMP, Not(ShiftLeft(1,Local4)),TEMP)
+ }
+ }
+
+ //
+ // Get GPIO Pad Ownership
+ //
+ Method(GGPO, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = PadOwnAddress + (PadNumber >> 3) * 0x4
+ Store( Add( GET_PAD_OWN_REG_ADDRESS(Local0) , Multiply( ShiftRight(Local1,3),0x4)),Local2)
+ OperationRegion(PREG, SystemMemory, Local2, 4)
+ Field(PREG, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ // PadOwnValue = (TEMP >> ((Local1 & 0x7) * 4)) & 0x3
+ Return( And( ShiftRight(TEMP,Multiply(And(Local1,0x7),0x4)),0x3))
+ }
+
+ //
+ // Set GPIO GPIRoutIOxAPIC value
+ //
+ Method(SGRA, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for GPIRoutIOxAPIC
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 20,
+ TEMP,1,
+ , 11
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Set GPIO weak pull-up/down value
+ //
+ Method(SGWP, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for weak pull-up/down
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + 0x4 + (GPIn * PAD_CFG_SIZE)
+ Store( Add( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),0x4),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 10,
+ TEMP,4,
+ , 18
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // ISME and CAGS methods are used to properly handle 2-tier GPE
+ // Example:
+ /*
+ Method(_L6F, 0) // Method which is called for all 2-tier GPE, must be within _GPE scope
+ {
+ If (\_SB.ISME(GpioPad))
+ {
+ \_SB.DeviceXYZ.GPEH() // Custom function to handle GPE for certain GPIO pad
+ \_SB.CAGS(GpioPad) // Clear 2-Tier GPE status
+ }
+ }
+ */
+
+ //
+ // @deprecated method, maintained for compatibility
+ // Will be removed in future generations
+ //
+ Method(UGPS, 0x0, Serialized) {
+
+ }
+
+ //
+ // Clear all GPE status for 2-tier
+ // @deprecated method, maintained for compatibility
+ // Will be removed in future generations
+ //
+ Method(CGPS, 0x0, Serialized) {
+
+ }
+
+ //
+ // Clear all GPE status for 2-tier which are level sensitive
+ // @deprecated method, maintained for compatibility
+ // Will be removed in future generations
+ //
+ Method(CGLS, 0x0, Serialized) {
+
+ }
+
+ //
+ // Clear a particular GPE status for 2-tier
+ //
+ Method(CAGS, 0x1, Serialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local4 - Additional offset to handle cases when GPIO group has more than 32 pads
+ Multiply(ShiftRight (Local1,5),4,Local4)
+
+ //Check if 2-tier
+ If (IS_GPIO_GROUP_IN_2_TIER_GPE(Local0)) {
+ //Get GPI_GPE_STS for GPP_x
+ OperationRegion(GPPX, SystemMemory, Add(GET_GPE_STS_REG_ADDRESS(Local0),Local4), 4)
+ Field(GPPX, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ STSX,32,
+ }
+ // Local2 - GpioPad bit mask within register
+ ShiftLeft(1, Mod(Local1,32), Local2)
+ // Clear GPIO status by writing 1b for a pad
+ Store(Local2, STSX)
+ }
+ }
+
+ //
+ // Check if GPIO pad was source of 2-Tier GPE event
+ //
+ Method(ISME, 0x1, NotSerialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ If (LNot(IS_GPIO_GROUP_IN_2_TIER_GPE(Arg0))) {
+ Return(0)
+ }
+
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local2 - Register offset = GpeStsRegOffset + (GpioPadNumber >> 5)*0x4
+ Add (GET_GPE_STS_REG_ADDRESS(Local0), Multiply (ShiftRight(Local1,5), 0x4), Local2)
+ // Local3 - Pad bit position within register, Local3 = GpioPad & 0x1F = GpioPad % 32
+ And (Local1, 0x1F, Local3)
+
+ OperationRegion(GPPX, SystemMemory, Local2, 0x24)
+ Field(GPPX, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ STSX,32,
+ Offset(0x20),
+ GENX,32
+ }
+
+ //Return result of GPI_GPE_EN&GPI_GPE_STS for this pad
+ Return(And(ShiftRight(And(STSX,GENX),Local3),0x1))
+ }
+
+ //
+ // Do Interrupt Pin Isolation
+ // This method should be called before power gating external device
+ // which uses Gpio pad as an interrupt
+ //
+ Method(DIPI, 0x1, Serialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 9,
+ RDIS,1,
+ , 15,
+ RCFG,2,
+ , 5
+ }
+ If(LNotEqual(RCFG,2)) {
+ // Save RxEvCfg state in RXEV object:
+ // RXEV[GroupIndex][PadNumber] = RCFG
+ Store(RCFG, Index( DeRefOf(Index(RXEV,Local0)), Local1))
+ // Set RxEvCfg to 2
+ Store(2,RCFG)
+ // Set GPIORxDis to 1
+ Store(1,RDIS)
+ }
+ }
+
+ //
+ // Undo Interrupt Pin Isolation
+ // This method should be called after un-power gating external device
+ // which uses Gpio pad as an interrupt
+ //
+ Method(UIPI, 0x1, Serialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 9,
+ RDIS,1,
+ , 15,
+ RCFG,2,
+ , 5
+ }
+ // Get RxEvCfg original value from RXEV object
+ // Local3 = RXEV[GroupIndex][PadNumber]
+ Store( DeRefOf(Index( DeRefOf(Index (RXEV, Local0)), Local1)), Local3)
+
+ If(LNotEqual(Local3,2)) {
+ // Set GPIORxDis to 0
+ Store(0,RDIS)
+ // Set RxEvCfg to original value
+ Store(Local3,RCFG)
+ }
+ }
+
+} // \_SB Scope
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl
new file mode 100644
index 0000000000..1468aedba4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl
@@ -0,0 +1,230 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#define PCH_LP_GPIO_GET_FIELD(GpioGroupIndex,GpioFieldIndex) \
+ ( \
+ DeRefOf(Index( \
+ DeRefOf(Index( \
+ GPCL, \
+ GpioGroupIndex)), \
+ GpioFieldIndex)) \
+ )
+
+#define PCH_H_GPIO_GET_FIELD(GpioGroupIndex,GpioFieldIndex) \
+ ( \
+ DeRefOf(Index( \
+ DeRefOf(Index( \
+ GPCH, \
+ GpioGroupIndex)), \
+ GpioFieldIndex)) \
+ )
+
+//
+// GPIO Library objects
+//
+Scope(\_SB)
+{
+
+ //
+ // GPIO information data structure
+ //
+ // PCH-LP: GPCL
+ // PCH-H: GPCH
+ //
+ // GPCx[GroupIndex][Field]
+ // Field0 - Community
+ // Field1 - Pad number
+ // Field2 - PADCFG register offset
+ // Field3 - HOSTSW_OWN register offset
+ // Field4 - PAD_OWN register offset
+ // Field5 - GPI_GPE_STS register offset
+ //
+ //
+ // GPIO information data structure for PCH-LP
+ //
+ Name(GPCL, Package(){
+ Package(){ // GPP_A
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_A_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_A_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS
+ },
+ Package(){ // GPP_B
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_B_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_B_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS
+ },
+ Package(){ // GPP_C
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_C_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_C_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS
+ },
+ Package(){ // GPP_D
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_D_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_D_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS
+ },
+ Package(){ // GPP_E
+ PCH_GPIO_COM1,
+ V_PCH_LP_GPIO_GPP_E_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_E_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS
+ },
+ Package(){ // GPP_F
+ PCH_GPIO_COM3,
+ V_PCH_GPIO_GPP_F_PAD_MAX,
+ R_PCH_LP_PCR_GPIO_GPP_F_PADCFG_OFFSET,
+ R_PCH_LP_PCR_GPIO_GPP_F_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_F_PAD_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_STS
+ },
+ Package(){ // GPP_G
+ PCH_GPIO_COM3,
+ V_PCH_LP_GPIO_GPP_G_PAD_MAX,
+ R_PCH_LP_PCR_GPIO_GPP_G_PADCFG_OFFSET,
+ R_PCH_LP_PCR_GPIO_GPP_G_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_G_PAD_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_STS
+ },
+ Package(){ // GPD
+ PCH_GPIO_COM2,
+ V_PCH_GPIO_GPD_PAD_MAX,
+ R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPD_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPD_PAD_OWN,
+ R_PCH_PCR_GPIO_GPD_GPI_GPE_STS
+ }
+ })
+
+ //
+ // GPIO information data structure for PCH-H
+ //
+ Name(GPCH, Package(){
+ Package(){ // GPP_A
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_A_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_A_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS
+ },
+ Package(){ // GPP_B
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_B_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_B_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS
+ },
+ Package(){ // GPP_C
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_C_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_C_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS
+ },
+ Package(){ // GPP_D
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_D_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_D_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS
+ },
+ Package(){ // GPP_E
+ PCH_GPIO_COM1,
+ V_PCH_H_GPIO_GPP_E_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_E_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS
+ },
+ Package(){ // GPP_F
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_F_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_F_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_F_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_F_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_STS
+ },
+ Package(){ // GPP_G
+ PCH_GPIO_COM1,
+ V_PCH_H_GPIO_GPP_G_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_G_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_G_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_G_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_STS
+ },
+ Package(){ // GPP_H
+ PCH_GPIO_COM1,
+ V_PCH_H_GPIO_GPP_H_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_H_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_H_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_H_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_STS
+ },
+ Package(){ // GPP_I
+ PCH_GPIO_COM3,
+ V_PCH_H_GPIO_GPP_I_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_I_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_I_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_I_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_STS
+ },
+ Package(){ // GPD
+ PCH_GPIO_COM2,
+ V_PCH_GPIO_GPD_PAD_MAX,
+ R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPD_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPD_PAD_OWN,
+ R_PCH_PCR_GPIO_GPD_GPI_GPE_STS
+ }
+ })
+
+ //
+ // Object for storing RX Level/Edge Configuration for all pads.
+ // One fields contains data for one pad.
+ // 00b = Level
+ // 01b = Edge (RxInv=0 for rising edge; 1 for falling edge)
+ // 10b = Disabled
+ // 11b = Either rising edge or falling edge
+ //
+ // Each row has data for one group. Buffer size needs
+ // to equal to number of pads
+ Name(RXEV, Package(){
+ Buffer(V_PCH_GPIO_GPP_A_PAD_MAX){}, // GPP_A
+ Buffer(V_PCH_GPIO_GPP_B_PAD_MAX){}, // GPP_B
+ Buffer(V_PCH_GPIO_GPP_C_PAD_MAX){}, // GPP_C
+ Buffer(V_PCH_GPIO_GPP_D_PAD_MAX){}, // GPP_D
+ Buffer(V_PCH_GPIO_GPP_E_PAD_MAX){}, // GPP_E
+ Buffer(V_PCH_GPIO_GPP_F_PAD_MAX){}, // GPP_F
+ Buffer(V_PCH_GPIO_GPP_G_PAD_MAX){}, // GPP_G
+ Buffer(V_PCH_H_GPIO_GPP_H_PAD_MAX){}, // PCH-H GPP_H, PCH-LP GPD
+ Buffer(V_PCH_H_GPIO_GPP_I_PAD_MAX){}, // PCH-H GPP_I, PCH-LP not used
+ Buffer(V_PCH_GPIO_GPD_PAD_MAX){} // PCH-H GPD, PCH-LP not used
+ })
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl
new file mode 100644
index 0000000000..51d88f1e5a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl
@@ -0,0 +1,616 @@
+/** @file
+ ACPI DSDT table
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+
+// Use this information when determining the Possible IRQs that can be
+// used in a given system.
+//
+// The following IRQs are always in use by legacy devices:
+// 0 = System Timer
+// 2 = 8259 PIC
+// 8 = RTC
+// 9 = SCI Interrupt (It may be used, we choose not to)
+// 13 = Co-processor Error
+//
+// The following may be in use by legacy devices:
+// 1 = If using PS/2 Keyboard
+// 3 = If COMx Port Enabled and IRQ = 3
+// 4 = If COMx Port Enabled and IRQ = 4
+// 5 = If LPT Port Enabled and IRQ = 5
+// 6 = If FDC Enabled
+// 7 = If LPT Port Enabled and IRQ = 7
+// 12 = If using PS/2 Mouse
+// 14 = Primary IDE (If populated and in Compatibility Mode)
+// 15 = Secondary IDE (If populated and in Compatibility Mode)
+//
+// The following will never be in use by legacy devices:
+// 10 = Assign to PARC, PCRC, PERC, PGRC
+// 11 = Assign to PBRC, PDRC, PFRC, PHRC
+
+Device(LNKA) // PARC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F")) // PCI Interrupt Link Device
+
+ Name(_UID,1) // Unique to other Link Devices
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PARC,0x80,\_SB.PARC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSA)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLA,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLA,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PARC,0x0F),IRQ0)
+
+ Return(RTLA)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PARC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PARC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKB) // PBRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,2)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PBRC,0x80,\_SB.PBRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSB)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLB,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLB,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PBRC,0x0F),IRQ0)
+
+ Return(RTLB)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PBRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PBRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKC) // PCRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,3)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PCRC,0x80,\_SB.PCRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSC)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLC,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLC,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PCRC,0x0F),IRQ0)
+
+ Return(RTLC)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PCRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PCRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKD) // PDRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,4)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PDRC,0x80,\_SB.PDRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSD)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLD,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLD,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PDRC,0x0F),IRQ0)
+
+ Return(RTLD)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PDRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PDRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKE) // PERC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,5)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PERC,0x80,\_SB.PERC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSE)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLE,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLE,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PERC,0x0F),IRQ0)
+
+ Return(RTLE)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PERC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PERC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKF) // PFRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,6)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PFRC,0x80,\_SB.PFRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSF)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLF,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLF,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PFRC,0x0F),IRQ0)
+
+ Return(RTLF)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PFRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PFRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKG) // PGRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,7)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PGRC,0x80,\_SB.PGRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSG)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLG,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLG,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PGRC,0x0F),IRQ0)
+
+ Return(RTLG)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PGRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PGRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKH) // PHRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,8)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PHRC,0x80,\_SB.PHRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSH)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLH,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLH,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PHRC,0x0F),IRQ0)
+
+ Return(RTLH)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PHRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PHRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl
new file mode 100644
index 0000000000..34f3f6877f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl
@@ -0,0 +1,1156 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PchAccess.h>
+
+Name (PNVB, 0xFFFF0000) // PCH NVS Base address
+Name (PNVL, 0xAA55) // PCH NVS Length
+Include ("PchNvs.asl")
+
+//
+// Include GPIO macros and access library
+//
+include("GpioAcpiDefines.h")
+include("GpioLib.asl")
+
+//
+// Trace Hub debug library
+// Include it earlier so the debug function can be used as soon as possible
+//
+Include ("TraceHubDebug.asl")
+
+Name(SPTH,1)
+Name(SPTL,2)
+Method(PCHV) {
+ If(LEqual(PCHS, 1)) { Return (SPTH) } // series=H -> SPT-H
+ If(LEqual(PCHS, 2)) { Return (SPTL) } // series=LP -> SPT-LP
+ Return (0)
+}
+
+//
+// This PME event (PCH's GPE 6Dh) is received when any PCH internal device with
+// PCI Power Management capabilities on bus 0 asserts the equivalent of the PME# signal.
+//
+Scope(\_GPE) {
+ Method(_L6D, 0, Serialized) {
+ \_SB.PCI0.XHC.GPEH()
+ \_SB.PCI0.HDAS.GPEH()
+ \_SB.PCI0.GLAN.GPEH()
+ \_SB.PCI0.XDCI.GPEH()
+ }
+}
+
+Scope (\_SB.PCI0) {
+
+ Name(TEMP,0) // scratch variable that does not cause compiler warnings as writes to Localx variables do.
+
+ //
+ // PCH reserved resource
+ //
+ Device(PRRE) {
+ Name(_HID,EISAID("PNP0C02")) // motherboard resource
+ Name(_UID,"PCHRESV")
+ Name(_STA,0x3) // device present and decodes its resources, but not to be displayed in OSPM
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(BUF0,ResourceTemplate(){
+ //
+ // PCH RESERVED MMIO RANGE
+ // 0xFD000000 to 0xFE7FFFFF
+ // to skip over address range that might be claimed by the GPIO, Intel Serial IO, Thermal, TraceHub and CIO2 devices
+ // need to split this into 5 ranges
+ // The GPIO COMM0,1,3 and SerialIO ranges will be handled by SIRC device.
+ //
+ Memory32Fixed(ReadWrite,0xFD000000,0x00AC0000) // 0xFD000000 - 0xFDABFFFF
+ // Skip 0xFDAC0000 - 0xFDACFFFF for GPIO_COMM3
+ Memory32Fixed(ReadWrite,0xFDAD0000,0x00010000) // 0xFDAD0000 - 0xFDADFFFF, only cover GPIO_COMM2 range
+ // Skip 0xFDAE0000 - 0xFDAFFFFF for GPIO_COMM0 and GPIO_COMM1
+ Memory32Fixed(ReadWrite,0xFDB00000,0x00500000) // 0xFDB00000 - 0xFDFFFFFF
+ Memory32Fixed(ReadWrite,0xFE000000,0x00020000) // 0xFE000000 - 0xFE01FFFF
+ // Skip 0xFE020000 - 0xFE035FFF for Serial IO
+ Memory32Fixed(ReadWrite,0xFE036000,0x00006000) // 0xFE036000 - 0xFE03BFFF
+ // Skip 0xFE03C000 - 0xFE03CFFF for Thermal Device in ACPI mode
+ Memory32Fixed(ReadWrite,0xFE03D000,0x003C3000) // 0xFE03D000 - 0xFE3FFFFF
+ // Skip 0xFE400000 - 0xFE40FFFF for CIO2 in ACPI mode
+ Memory32Fixed(ReadWrite,0xFE410000,0x003F0000) // 0xFE410000 - 0xFE7FFFFF
+ })
+ Return(BUF0)
+ }
+ }
+ Device(IOTR) {
+ //
+ // This device claims IO range reserved for IO traps
+ // to prevent OS from reusing it for other purposes
+ //
+ Name(_HID,EISAID("PNP0C02"))
+ Name(_UID,"IoTraps")
+ Method(_CRS) {
+ Store(ResourceTemplate() { }, Local0)
+ Name(BUF0,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG0) })
+ Name(BUF1,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG1) })
+ Name(BUF2,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG2) })
+ Name(BUF3,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG3) })
+ CreateWordField(BUF0,TAG0._MIN,AMI0);CreateWordField(BUF0,TAG0._MAX,AMA0)
+ CreateWordField(BUF1,TAG1._MIN,AMI1);CreateWordField(BUF1,TAG1._MAX,AMA1)
+ CreateWordField(BUF2,TAG2._MIN,AMI2);CreateWordField(BUF2,TAG2._MAX,AMA2)
+ CreateWordField(BUF3,TAG3._MIN,AMI3);CreateWordField(BUF3,TAG3._MAX,AMA3)
+ Store(ITA0,AMI0);Store(ITA0,AMA0)
+ Store(ITA1,AMI1);Store(ITA1,AMA1)
+ Store(ITA2,AMI2);Store(ITA2,AMA2)
+ Store(ITA3,AMI3);Store(ITA3,AMA3)
+ // Win7 can't store result of ConcatenateResTemplate directly into one of its input parameters
+ if(LEqual(ITS0,1)) { ConcatenateResTemplate(Local0, BUF0, Local1); Store(Local1, Local0) }
+ if(LEqual(ITS1,1)) { ConcatenateResTemplate(Local0, BUF1, Local1); Store(Local1, Local0) }
+ if(LEqual(ITS2,1)) { ConcatenateResTemplate(Local0, BUF2, Local1); Store(Local1, Local0) }
+ if(LEqual(ITS3,1)) { ConcatenateResTemplate(Local0, BUF3, Local1); Store(Local1, Local0) }
+ return (Local0)
+ }
+ }
+
+
+ //
+ // LPC Bridge - Device 31, Function 0, this is only for PCH register Memory Region declare,
+ // it's better to be declared as early as possible since it's widely used in whole ACPI name space.
+ // Please add any code which needs to reference any register of it after this
+ //
+ Device(LPCB) {
+ Name(_ADR, 0x001F0000)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+
+ OperationRegion(LPC, PCI_Config, 0x00, 0x100)
+ Field(LPC, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x02),
+ CDID, 16,
+ Offset(0x08),
+ CRID, 8,
+ Offset(R_PCH_LPC_IOD), // 0x80
+ IOD0, 8,
+ IOD1, 8,
+ Offset(0xA0),
+ , 9,
+ PRBL, 1,
+ Offset(R_PCH_LPC_BC), // 0xDC
+ , 2,
+ ESPI, 1,
+ }
+ }
+
+ //
+ // PCH Power Management Controller
+ //
+ Device(PPMC) {
+ Name(_ADR, 0x001F0002)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // SMBus Controller - Device 31, Function 4
+ //
+ Device(SBUS) {
+ Name(_ADR,0x001F0004)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+}
+
+scope(\_SB) {
+ Include ("IrqLink.asl")
+}
+
+Scope(\)
+{
+ //
+ // PCR Register Access Methods
+ //
+ // PCR Dword Read
+ // arg0: PID
+ // arg1: Offset
+ //
+ Method (PCRR, 2, Serialized) {
+ Add (ShiftLeft (arg0, 16), arg1, Local0)
+ Add (SBRG, Local0, Local0)
+ OperationRegion (PCR0, SystemMemory, Local0, 0x4)
+ Field(PCR0,DWordAcc,Lock,Preserve) {
+ Offset(0x00),
+ DAT0, 32
+ } // End Field PCR0
+ Return (DAT0)
+ } // End Method PCRR
+
+ //
+ // PCR Dword Write
+ // arg0: PID
+ // arg1: Offset
+ // arg2: write data
+ //
+ Method (PCRW, 3, Serialized) {
+ Add (ShiftLeft (arg0, 16), arg1, Local0)
+ Add (SBRG, Local0, Local0)
+ OperationRegion (PCR0, SystemMemory, Local0, 0x4)
+ Field(PCR0,DWordAcc,Lock,Preserve) {
+ Offset(0x00),
+ DAT0, 32
+ } // End Field PCR0
+ Store (arg2, DAT0)
+ // read back for PCR back to back limitation
+ Store (PCRR (PID_LPC, R_PCH_PCR_RTC_RTCDCG), local0)
+ } // End Method PCRW
+
+ //
+ // PCR Dword Or
+ // arg0: PID
+ // arg1: Offset
+ // arg2: Or data
+ //
+ Method (PCRO, 3, Serialized) {
+ Store(PCRR(arg0,arg1),Local0) // Store PCR Read data in Local0
+ Store(Or(Local0,arg2),Local1) // Or data
+ PCRW(arg0,arg1,Local1) // Write data back
+ }
+
+ //
+ // PCR Dword And
+ // arg0: PID
+ // arg1: Offset
+ // arg2: And data
+ //
+ Method (PCRA, 3, Serialized) {
+ Store(PCRR(arg0,arg1),Local0) // Store PCR Read data in Local0
+ Store(And(Local0,arg2),Local1) // And data
+ PCRW(arg0,arg1,Local1) // Write data back
+ }
+
+ //
+ // PCR Dword AndThenOr
+ // arg0: PID
+ // arg1: Offset
+ // arg2: And data
+ // arg3: Or data
+ //
+ Method (PCAO, 4, Serialized) {
+ Store(PCRR(arg0,arg1),Local0) // Store PCR Read data in Local0
+ Store(Or(And(Local0,arg2),arg3),Local1) // AndThenOr
+ PCRW(arg0,arg1,Local1) // Write data back
+ }
+
+ Name (TCBV, 0) // TCO I/O base address value
+ Method (TCBS, 0) {
+ If (LEqual(TCBV, 0)) {
+ // PCR[DMI] + 2778h[15:5]
+ Store(PCRR (PID_DMI, R_PCH_PCR_DMI_TCOBASE),Local0)
+ And(Local0,B_PCH_PCR_DMI_TCOBASE_TCOBA,TCBV)
+ }
+ Return (TCBV)
+ }
+
+ //
+ // Define PCH ACPIBASE I/O as an ACPI operating region. The base address
+ // can be found in Device 31, Function 2, Offset 40h.
+ //
+ OperationRegion(PMIO, SystemIo, PMBS, 0x60)
+ Field(PMIO, ByteAcc, NoLock, Preserve) {
+ , 8,
+ PBSS, 1, // Power Button Status
+ Offset(R_PCH_ACPI_GPE_CNTL), // 0x40, General Purpose Event Control
+ , 17,
+ GPEC, 1 // Software GPE Control
+ }
+
+ //
+ // Define PCH TCOBASE I/O
+ //
+ OperationRegion(TCBA, SystemIo, TCBS, 0x10)
+ Field(TCBA, ByteAcc, NoLock, Preserve) {
+ Offset(R_PCH_TCO1_STS), // 0x04
+ , 9,
+ CPSC, 1, // CPUSCI_STS
+ }
+
+ //
+ // PWRM register definitions
+ //
+ OperationRegion(PWMR, SystemMemory, \PWRM, 0x800)
+ Field(PWMR, AnyAcc, NoLock, Preserve) {
+ Offset(R_PCH_PWRM_CFG3), // 0xE0
+ , 16,
+ DWLE, 1, // Deep-Sx WLAN Phy Power Enable
+ HWLE, 1, // Host Wireless LAN Phy Power Enable
+ Offset(R_PCH_PWRM_31C), // 0x31C
+ , 13,
+ SLS0, 1, // SLP_S0# Low Voltage Mode Enable (SLPS0LVEN)
+ , 8,
+ XSQD, 1, // 24MHz Crystal Shutdown Qualification Disable (XTALSDQDIS)
+ }
+
+ //
+ //
+ OperationRegion(PMST, SystemMemory, PWRM, 0x80)
+ Field(PMST, DWordAcc, NoLock, Preserve) {
+ Offset(R_PCH_PWRM_CFG), // 0x18, Power Management Configuration Reg 1 (PM_CFG)
+ , 25, //
+ USBP, 1, // Allow USB2 PHY Core Power Gating (ALLOW_USB2_CORE_PG)
+ Offset(R_PCH_PWRM_PCH_PM_STS), // 0x1C, PCH Power Management Status (PCH_PM_STS)
+ , 24, //
+ PMFS, 1, // PMC Message Full Status (PMC_MSG_FULL_STS)
+ Offset(R_PCH_PWRM_MTPMC), // 0x20, Message to PMC (MTPMC)
+ MPMC, 32, // Message to PMC (MTPMC)
+ Offset(R_PCH_PWRM_PCH_PM_STS2), // 0x24, PCH Power Management Status (PCH_PM_STS2)
+ , 20, //
+ UWAB, 1, // USB2 Workaround Available Bit
+ }
+
+} //end Scope(\)
+
+Scope (\_SB.PCI0) {
+ Name(LTRZ, 0)
+ Name(OBFZ, 0)
+
+ Name(LMSL, 0)
+ Name(LNSL, 0)
+
+ //
+ // LAN Controller - Device 31, Function 6
+ //
+ Device(GLAN) { // GbE Controller
+ Name(_ADR, 0x001F0006)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ OperationRegion(GLBA, PCI_Config, 0,0x100)
+ Field(GLBA,AnyAcc,NoLock,Preserve)
+ {
+ DVID, 16
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field(GLBA,ByteAcc,NoLock,Preserve)
+ {
+ Offset(R_PCH_LAN_PMCS), // 0xCC
+ , 8,
+ PMEE, 1, // PME Enable
+ , 6,
+ PMES, 1 // PME Status
+ }
+
+ Method(_PRW, 0) { Return(GPRW(0x6D, 4)) } // can wakeup from S4 state
+
+ Method(_DSW, 3)
+ {
+ Store(Arg0, PMEE)
+ }
+
+ //
+ // GPE handler for GbE, this is part of _Lxx handler for bus 0 PME
+ //
+ Method(GPEH)
+ {
+ If(LEqual(DVID, 0xFFFF)) {
+ Return()
+ }
+ If(LAnd(PMEE, PMES)) {
+ Store(1, PMES) // clear PME Status
+ Notify(GLAN, 0x02)
+ }
+ }
+ } // end "GbE Controller"
+
+} //scope
+
+//
+// xHCI Controller - Device 20, Function 0
+//
+Include("PchXhci.asl")
+
+//
+// xDCI (OTG) Controller - Device 20, Function 1
+//
+include("PchXdci.asl")
+
+Scope(\_SB_.PCI0) {
+ //
+ // High Definition Audio Controller - Device 31, Function 3
+ //
+ include("PchHda.asl")
+
+ //
+ // PCIE Root Port #01
+ //
+ Device(RP01) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA1,0)) {
+ Return (RPA1)
+ } Else {
+ Return (0x001C0000)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR1, LTRZ)
+ Store (PML1, LMSL)
+ Store (PNL1, LNSL)
+ Store (OBF1, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #01"
+
+ //
+ // PCIE Root Port #02
+ //
+ Device(RP02) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA2,0)) {
+ Return (RPA2)
+ } Else {
+ Return (0x001C0001)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR2, LTRZ)
+ Store (PML2, LMSL)
+ Store (PNL2, LNSL)
+ Store (OBF2, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #02"
+
+ //
+ // PCIE Root Port #03
+ //
+ Device(RP03) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA3,0)) {
+ Return (RPA3)
+ } Else {
+ Return (0x001C0002)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR3, LTRZ)
+ Store (PML3, LMSL)
+ Store (PNL3, LNSL)
+ Store (OBF3, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #03"
+
+ //
+ // PCIE Root Port #04
+ //
+ Device(RP04) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA4,0)) {
+ Return (RPA4)
+ } Else {
+ Return (0x001C0003)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR4, LTRZ)
+ Store (PML4, LMSL)
+ Store (PNL4, LNSL)
+ Store (OBF4, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #04"
+
+ //
+ // PCIE Root Port #05
+ //
+ Device(RP05) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA5,0)) {
+ Return (RPA5)
+ } Else {
+ Return (0x001C0004)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR5, LTRZ)
+ Store (PML5, LMSL)
+ Store (PNL5, LNSL)
+ Store (OBF5, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #05"
+
+ //
+ // PCIE Root Port #06
+ //
+ Device(RP06) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA6,0)) {
+ Return (RPA6)
+ } Else {
+ Return (0x001C0005)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR6, LTRZ)
+ Store (PML6, LMSL)
+ Store (PNL6, LNSL)
+ Store (OBF6, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #06"
+
+ //
+ // PCIE Root Port #07
+ //
+ Device(RP07) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA7,0)) {
+ Return (RPA7)
+ } Else {
+ Return (0x001C0006)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR7, LTRZ)
+ Store (PML7, LMSL)
+ Store (PNL7, LNSL)
+ Store (OBF7, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) } // APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #07"
+
+ //
+ // PCIE Root Port #08
+ //
+ Device(RP08) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA8,0)) {
+ Return (RPA8)
+ } Else {
+ Return (0x001C0007)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR8, LTRZ)
+ Store (PML8, LMSL)
+ Store (PNL8, LNSL)
+ Store (OBF8, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #08"
+
+ //
+ // PCIE Root Port #09
+ //
+ Device(RP09) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA9,0)) {
+ Return (RPA9)
+ } Else {
+ Return (0x001D0000)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR9, LTRZ)
+ Store (PML9, LMSL)
+ Store (PNL9, LNSL)
+ Store (OBF9, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #09"
+
+ //
+ // PCIE Root Port #10
+ //
+ Device(RP10) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAA,0)) {
+ Return (RPAA)
+ } Else {
+ Return (0x001D0001)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRA, LTRZ)
+ Store (PMLA, LMSL)
+ Store (PNLA, LNSL)
+ Store (OBFA, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #10"
+
+ //
+ // PCIE Root Port #11
+ //
+ Device(RP11) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAB,0)) {
+ Return (RPAB)
+ } Else {
+ Return (0x001D0002)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRB, LTRZ)
+ Store (PMLB, LMSL)
+ Store (PNLB, LNSL)
+ Store (OBFB, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #11"
+
+ //
+ // PCIE Root Port #12
+ //
+ Device(RP12) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAC,0)) {
+ Return (RPAC)
+ } Else {
+ Return (0x001D0003)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRC, LTRZ)
+ Store (PMLC, LMSL)
+ Store (PNLC, LNSL)
+ Store (OBFC, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #12"
+
+ //
+ // PCIE Root Port #13
+ //
+ Device(RP13) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAD,0)) {
+ Return (RPAD)
+ } Else {
+ Return (0x001D0004)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRD, LTRZ)
+ Store (PMLD, LMSL)
+ Store (PNLD, LNSL)
+ Store (OBFD, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #13"
+
+ //
+ // PCIE Root Port #14
+ //
+ Device(RP14) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAE,0)) {
+ Return (RPAE)
+ } Else {
+ Return (0x001D0005)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRE, LTRZ)
+ Store (PMLE, LMSL)
+ Store (PNLE, LNSL)
+ Store (OBFE, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #14"
+
+ //
+ // PCIE Root Port #15
+ //
+ Device(RP15) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAF,0)) {
+ Return (RPAF)
+ } Else {
+ Return (0x001D0006)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRF, LTRZ)
+ Store (PMLF, LMSL)
+ Store (PNLF, LNSL)
+ Store (OBFF, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #15"
+
+ //
+ // PCIE Root Port #16
+ //
+ Device(RP16) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAG,0)) {
+ Return (RPAG)
+ } Else {
+ Return (0x001D0007)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRG, LTRZ)
+ Store (PMLG, LMSL)
+ Store (PNLG, LNSL)
+ Store (OBFG, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #16"
+
+ //
+ // PCIE Root Port #17
+ //
+ Device(RP17) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAH,0)) {
+ Return (RPAH)
+ } Else {
+ Return (0x001B0000)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRH, LTRZ)
+ Store (PMLH, LMSL)
+ Store (PNLH, LNSL)
+ Store (OBFH, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #17"
+
+ //
+ // PCIE Root Port #18
+ //
+ Device(RP18) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAI,0)) {
+ Return (RPAI)
+ } Else {
+ Return (0x001B0001)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRI, LTRZ)
+ Store (PMLI, LMSL)
+ Store (PNLI, LNSL)
+ Store (OBFI, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #18"
+
+ //
+ // PCIE Root Port #19
+ //
+ Device(RP19) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAJ,0)) {
+ Return (RPAJ)
+ } Else {
+ Return (0x001B0002)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRJ, LTRZ)
+ Store (PMLJ, LMSL)
+ Store (PNLJ, LNSL)
+ Store (OBFJ, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #19"
+
+ //
+ // PCIE Root Port #20
+ //
+ Device(RP20) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAK,0)) {
+ Return (RPAK)
+ } Else {
+ Return (0x001B0003)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRK, LTRZ)
+ Store (PMLK, LMSL)
+ Store (PNLK, LNSL)
+ Store (OBFK, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #20"
+
+ //
+ // PCIE Root Port #21
+ //
+ Device(RP21) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAL,0)) {
+ Return (RPAL)
+ } Else {
+ Return (0x001B0004)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRL, LTRZ)
+ Store (PMLL, LMSL)
+ Store (PNLL, LNSL)
+ Store (OBFL, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #21"
+
+ //
+ // PCIE Root Port #21
+ //
+ Device(RP22) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAM,0)) {
+ Return (RPAM)
+ } Else {
+ Return (0x001B0005)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRM, LTRZ)
+ Store (PMLM, LMSL)
+ Store (PNLM, LNSL)
+ Store (OBFM, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #22"
+
+ //
+ // PCIE Root Port #22
+ //
+ Device(RP23) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAN,0)) {
+ Return (RPAN)
+ } Else {
+ Return (0x001B0006)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRN, LTRZ)
+ Store (PMLN, LMSL)
+ Store (PNLN, LNSL)
+ Store (OBFN, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #23"
+
+ //
+ // PCIE Root Port #21
+ //
+ Device(RP24) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAO,0)) {
+ Return (RPAO)
+ } Else {
+ Return (0x001B0007)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRO, LTRZ)
+ Store (PMLO, LMSL)
+ Store (PNLO, LNSL)
+ Store (OBFO, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #24"
+
+ //
+ // Serial ATA Host Controller - Device 31, Function 2
+ //
+ Include ("PchSata.asl")
+
+ //
+ // CIO2 ACPI device - Device 20, Function 3
+ //
+ Device (CIO2) {
+ Method (_STA) {
+ If (LEqual(CIOE,1)){ Return (0x0F) }
+ Else { Return (0x00) }
+ }
+ Name(_HID, "INT343E")
+ Method(_CRS, 0, NotSerialized) {
+ Name(CBUF, ResourceTemplate () {
+ Interrupt(ResourceConsumer, Level, ActiveLow, Shared,,,CIOD) {0x10}
+ Memory32Fixed (ReadWrite, PCH_CIO2_BASE_ADDRESS, PCH_CIO2_MMIO_SIZE)
+ })
+ CreateDWordField(CBUF,CIOD._INT,CIOV)
+ Store(CIOI, CIOV)
+ Return (CBUF)
+ }
+ }
+
+ //
+ // Thermal Device
+ //
+ Device(TERM) {
+ Name (_HID, "INT343D")
+ Name (_UID, 1)
+
+ Method (_CRS, 0x0, NotSerialized) {
+ Name (RBUF, ResourceTemplate () {
+ Memory32Fixed (ReadWrite, PCH_THERMAL_BASE_ADDRESS, PCH_THERMAL_MMIO_SIZE, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , IRQ) { 18 }
+ })
+
+ CreateDWordField(RBUF,IRQ._INT,IRQN)
+
+ Store(TIRQ, IRQN)
+
+ Return (RBUF)
+ }
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ If(LEqual(TAEN, 0)) { Return(0x0) } // device not enabled in ACPI mode
+ If(LEqual(TIRQ, 0)) { Return(0x0) } // IRQ number not updated
+ Return(0xF)
+ }
+ }
+}
+
+
+//
+// Serial IO Controllers definitions
+//
+#define SERIAL_SCOPE \_SB.PCI0
+Include ("PchSerialIo.asl")
+
+//
+// Storage and Communication Subsystems definitions
+//
+Include ("PchScs.asl")
+
+//
+// Integrated Sensor Hub definition
+//
+Include ("PchIsh.asl")
+
+//
+// MEI 1 definition
+//
+Include ("PchHeci.asl")
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf
new file mode 100644
index 0000000000..ec99fb847a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for the PCH ACPI tables
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010005
+BASE_NAME = PchAcpiTables
+FILE_GUID = 31401EE7-1600-437c-A11C-B1035D8E6070
+MODULE_TYPE = USER_DEFINED
+VERSION_STRING = 1.0
+
+[Sources]
+ Pch.asl
+ PchNvs.asl
+ PchHda.asl
+ PchSerialIo.asl
+ PchPcie.asl
+ PchSata.asl
+ PchRstPcieStorage.asl
+ UsbSbd.asl
+ PchXhci.asl
+ PchXdci.asl
+ IrqLink.asl
+ GpioLib.asl
+ TraceHubDebug.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl
new file mode 100644
index 0000000000..151ee1fdd8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl
@@ -0,0 +1,213 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+External(\_SB.PCI0.HDAS.PS0X, MethodObj)
+External(\_SB.PCI0.HDAS.PS3X, MethodObj)
+External(\_SB.PCI0.HDAS.PPMS, MethodObj)
+External(HIDW, MethodObj)
+External(HIWC, MethodObj)
+
+//
+// High Definition Audio Controller - Device 31, Function 3
+//
+Device(HDAS)
+{
+ Name(_ADR, 0x001F0003)
+
+ //
+ // Define a Memory Region that will allow access to the HDA PCI Configuration Space
+ //
+ OperationRegion(HDAR, PCI_Config, 0x00, 0x100)
+ Field(HDAR,WordAcc,NoLock,Preserve) {
+ VDID,32 // 0x00, VID DID
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field(HDAR,ByteAcc,NoLock,Preserve) {
+ Offset(R_PCH_HDA_PCS), // 0x54, Power Management Control and Status Register
+ ,8,
+ PMEE,1, // PME Enable
+ ,6,
+ PMES,1 // PME Status
+ }
+
+ Name(_S0W, 3) // Device can wake itself from D3 in S0
+
+ Method(_DSW, 3) { Store(Arg0, PMEE) } // Device wake enable
+
+ Method(_PRW, 0) { Return(GPRW(0x6D, 4)) } // Can wakeup from S4 state
+
+ // GPE handler for HDA, this is part of _Lxx handler for bus 0 PME
+ Method(GPEH) {
+ If(LEqual(VDID, 0xFFFFFFFF)) {
+ Return()
+ }
+
+ If(LAnd(PMEE, PMES)) {
+ ADBG("HDAS GPEH")
+ Store(1, PMES) // clear PME Status
+ Notify(HDAS, 0x02)
+ }
+ }
+
+ // D0 Method for HD-A Controller
+ Method(_PS0, 0, Serialized)
+ {
+
+
+ //
+ // Call platform HDAS PS0 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.HDAS.PS0X)) {
+ \_SB.PCI0.HDAS.PS0X()
+ }
+ }
+
+ // D3 Method for HD-A Controller
+ Method(_PS3, 0, Serialized)
+ {
+
+
+ //
+ // Call platform HDAS PS3 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.HDAS.PS3X)) {
+ \_SB.PCI0.HDAS.PS3X()
+ }
+ }
+
+ // NHLT Table memory descriptor, returned from _DSM
+ Name(NBUF, ResourceTemplate () {
+ // NHLT table address (_MIN = NHLT 64bit pointer, _MAX = _MIN + _LEN - 1) and length (_LEN)
+ QWordMemory (ResourceConsumer, , MinNotFixed, MaxNotFixed, NonCacheable, ReadOnly,
+ 0x1, // AddressGranularity
+ 0x0000000000000000, // AddressMinimum _MIN
+ 0x0000000000000000, // AddressMaximum _MAX
+ 0x0,
+ 0x0, // RangeLength _LEN
+ , , NHLT, AddressRangeACPI,)
+ })
+ Method(_INI) {
+ // Update resource according to NVS
+ ADBG("HDAS _INI")
+
+ // Set NHLT base address and length
+ CreateQWordField(NBUF, ^NHLT._MIN, NBAS)
+ CreateQWordField(NBUF, ^NHLT._MAX, NMAS)
+ CreateQWordField(NBUF, ^NHLT._LEN, NLEN)
+ Store(NHLA, NBAS)
+ Add(NHLA, Subtract(NHLL, 1), NMAS)
+ Store(NHLL, NLEN)
+
+ }
+
+ Method(_DSM, 0x4, NotSerialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ // Arg0 - UUID: A69F886E-6CEB-4594-A41F-7B5DCE24C553 (Buffer)
+ // Arg1 - Revision ID: 0x01 (Integer)
+ // Arg2 - Function Index: 0x0 - 0x3 (Integer) - See below for details.
+ // Arg3 - Depends on Function Index - See below for details.
+ // Return - Depends on Function Index - See below for details.
+
+ ADBG("HDAS _DSM")
+
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ // Verify UUID
+ If (LEqual(Arg0, ToUUID ("A69F886E-6CEB-4594-A41F-7B5DCE24C553"))) {
+
+ Switch(ToInteger(Arg2)) {
+
+ // Function 0: Function Support Query
+ // Arg2 - Function Index: 0x00 (Integer)
+ // Arg3: Unused
+ // Return: Bitmask of functions supported. (Buffer)
+ Case(0) {
+ // Supports function 0 - 3
+ Return(Buffer(One) { 0x0F })
+ }
+
+ // Function 1: Query Non HD Audio Descriptor Table
+ // Used by the Intel Offload Engine Driver to discover the
+ // non HD Audio devices supported by the Audio DSP.
+ // Arg2 - Function Index: 0x01 (Integer)
+ // Arg3 - Unused
+ // Return - ACPI Table describing the non HD Audio links and devices supported by the ADSP (ResourceBuffer)
+ Case(1) {
+ ADBG("_DSM Fun 1 NHLT")
+ // NBUF - Memory Resource Descriptor buffer with address and length of NHLT
+ Return(NBUF)
+ }
+
+ // Function 2: Query Feature Mask
+ // Used by the Intel Offload Engine Driver to retrieve a bitmask
+ // of features allowable on this platform.
+ // Arg2 - Function Index: 0x02 (Integer)
+ // Arg3: Unused
+ // Return: Bitmask of supported features.
+ Case (2) {
+ ADBG("_DSM Fun 2 FMSK")
+ // Bit 0 == '1', WoV is supported, Bit 0 == '0', WoV not supported
+ // Bit 1 == '1', BT Sideband is supported, Bit 1 == '0', BT not supported
+ // Bit 2 == '1', codec based VAD support allowable
+ // Bit 3 - 4 Reserved
+ // Bit 5 == '1', BT Intel HFP SCO is supported
+ // Bit 6 == '1', BT Intel A2DP is supported
+ // Bit 7 == '1', DSP based speech pre-processing disabled
+ // Bit 8 == '1', Windows Voice Activation, Bit 8 == '0', Intel Wake on Voice
+ // Bit 9 - 31 Reserved, shall be set to '0'
+ // ADFM - NVS AudioDSP Feature Bit Mask updated from PchPolicy
+ Return(ADFM)
+ }
+
+ // Function 3: Query Pre/Post Processing Module Support
+ // Used by the Intel Offload Engine Driver to determine if a
+ // specified PP Module is allowed to be supported on this platform
+ // Arg2 - Function Index: 0x03 (Integer)
+ // Arg3 - UUID: Specifies the UUID of the PP module to check (Buffer)
+ // Return - TRUE if PP Module supported, else FALSE.
+ Case (3) {
+ ADBG("_DSM Fun 3 PPMS")
+
+ If(CondRefOf(\_SB.PCI0.HDAS.PPMS)) {
+ // Call platform method PPMS to check if 3rd Party IP module with given GUID (Arg3) is supported
+ Return(\_SB.PCI0.HDAS.PPMS (Arg3))
+ }
+
+ Return(0) // Is not supported
+ }
+
+ Default {
+ // Function not supported (Arg2)
+ ADBG("_DSM Fun NOK")
+ Return(Buffer(One) { 0x00 })
+ }
+ } // Switch(Arg2) End
+ } // If(Arg0, UUID) End
+
+ //-------------------------------------------
+ // HID Wake up Event solution
+ //-------------------------------------------
+ If(CondRefOf(HIWC)) {
+ If(HIWC(Arg0)) {
+ If(CondRefOf(HIDW)) {
+ Return (HIDW(Arg0, Arg1, Arg2, Arg3))
+ }
+ }
+ }
+
+ // UUID not supported (Arg0)
+ ADBG("_DSM UUID NOK")
+ Return(Buffer() {0})
+ } // _DSM End
+} // end "High Definition Audio Controller"
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl
new file mode 100644
index 0000000000..c79ee8d6cd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl
@@ -0,0 +1,43 @@
+/**@file
+ ACPI DSDT table for MEI1
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+External(HIDW, MethodObj)
+External(HIWC, MethodObj)
+
+Scope(\_SB.PCI0) {
+ //
+ // Management Engine Interface 1 - Device 22, Function 0
+ //
+ Device(HECI) {
+ Name(_ADR, 0x00160000)
+
+ Method(_DSM, 0x4, NotSerialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ //-------------------------------------------
+ // HID Wake up Event solution
+ //-------------------------------------------
+ If(CondRefOf(HIWC)) {
+ If(HIWC(Arg0)) {
+ If(CondRefOf(HIDW)) {
+ Return (HIDW(Arg0, Arg1, Arg2, Arg3))
+ }
+ }
+ }
+
+ Return(Buffer() {0})
+ } // End _DSM
+ } // Device(HECI)
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl
new file mode 100644
index 0000000000..42f12ff266
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl
@@ -0,0 +1,42 @@
+/**@file
+ ACPI DSDT table for ISH
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+External(HIDW, MethodObj)
+External(HIWC, MethodObj)
+
+Scope(\_SB.PCI0) {
+ //
+ // Integrated Sensor Hub (PCI Mode) - Device 19, Function 0
+ //
+ Device(ISHD) {
+ Name(_ADR, 0x00130000)
+
+ Method(_DSM, 0x4, NotSerialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ //-------------------------------------------
+ // HID Wake up Event solution
+ //-------------------------------------------
+ If(CondRefOf(HIWC)) {
+ If(HIWC(Arg0)) {
+ If(CondRefOf(HIDW)) {
+ Return (HIDW(Arg0, Arg1, Arg2, Arg3))
+ }
+ }
+ }
+
+ Return(Buffer() {0})
+ } // End _DSM
+ } // Device(ISHD)
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl
new file mode 100644
index 0000000000..7c4a0cc23c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl
@@ -0,0 +1,240 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+ //
+ // Define PCH NVS Area operatino region.
+ //
+
+
+
+ OperationRegion(PNVA,SystemMemory,PNVB,PNVL)
+ Field(PNVA,AnyAcc,Lock,Preserve)
+ {
+ Offset(0), PCHS, 16, // Offset(0), PCH Series
+ Offset(2), PCHG, 16, // Offset(2), PCH Generation
+ Offset(4), RPA1, 32, // Offset(4), Root Port address 1
+ Offset(8), RPA2, 32, // Offset(8), Root Port address 2
+ Offset(12), RPA3, 32, // Offset(12), Root Port address 3
+ Offset(16), RPA4, 32, // Offset(16), Root Port address 4
+ Offset(20), RPA5, 32, // Offset(20), Root Port address 5
+ Offset(24), RPA6, 32, // Offset(24), Root Port address 6
+ Offset(28), RPA7, 32, // Offset(28), Root Port address 7
+ Offset(32), RPA8, 32, // Offset(32), Root Port address 8
+ Offset(36), RPA9, 32, // Offset(36), Root Port address 9
+ Offset(40), RPAA, 32, // Offset(40), Root Port address 10
+ Offset(44), RPAB, 32, // Offset(44), Root Port address 11
+ Offset(48), RPAC, 32, // Offset(48), Root Port address 12
+ Offset(52), RPAD, 32, // Offset(52), Root Port address 13
+ Offset(56), RPAE, 32, // Offset(56), Root Port address 14
+ Offset(60), RPAF, 32, // Offset(60), Root Port address 15
+ Offset(64), RPAG, 32, // Offset(64), Root Port address 16
+ Offset(68), RPAH, 32, // Offset(68), Root Port address 17
+ Offset(72), RPAI, 32, // Offset(72), Root Port address 18
+ Offset(76), RPAJ, 32, // Offset(76), Root Port address 19
+ Offset(80), RPAK, 32, // Offset(80), Root Port address 20
+ Offset(84), RPAL, 32, // Offset(84), Root Port address 21
+ Offset(88), RPAM, 32, // Offset(88), Root Port address 22
+ Offset(92), RPAN, 32, // Offset(92), Root Port address 23
+ Offset(96), RPAO, 32, // Offset(96), Root Port address 24
+ Offset(100), NHLA, 64, // Offset(100), HD-Audio NHLT ACPI address
+ Offset(108), NHLL, 32, // Offset(108), HD-Audio NHLT ACPI length
+ Offset(112), ADFM, 32, // Offset(112), HD-Audio DSP Feature Mask
+ Offset(116), SBRG, 32, // Offset(116), SBREG_BAR
+ Offset(120), GPEM, 32, // Offset(120), GPP_X to GPE_DWX mapping
+ Offset(124), G2L0, 32, // Offset(124), GPE 2-tier level edged enabled Gpio pads (Group Index 0)
+ Offset(128), G2L1, 32, // Offset(128), GPE 2-tier level edged enabled Gpio pads (Group Index 1)
+ Offset(132), G2L2, 32, // Offset(132), GPE 2-tier level edged enabled Gpio pads (Group Index 2)
+ Offset(136), G2L3, 32, // Offset(136), GPE 2-tier level edged enabled Gpio pads (Group Index 3)
+ Offset(140), G2L4, 32, // Offset(140), GPE 2-tier level edged enabled Gpio pads (Group Index 4)
+ Offset(144), G2L5, 32, // Offset(144), GPE 2-tier level edged enabled Gpio pads (Group Index 5)
+ Offset(148), G2L6, 32, // Offset(148), GPE 2-tier level edged enabled Gpio pads (Group Index 6)
+ Offset(152), G2L7, 32, // Offset(152), GPE 2-tier level edged enabled Gpio pads (Group Index 7)
+ Offset(156), G2L8, 32, // Offset(156), GPE 2-tier level edged enabled Gpio pads (Group Index 8)
+ Offset(160), G2L9, 32, // Offset(160), GPE 2-tier level edged enabled Gpio pads (Group Index 9)
+ Offset(164), PML1, 16, // Offset(164), PCIE LTR max snoop Latency 1
+ Offset(166), PML2, 16, // Offset(166), PCIE LTR max snoop Latency 2
+ Offset(168), PML3, 16, // Offset(168), PCIE LTR max snoop Latency 3
+ Offset(170), PML4, 16, // Offset(170), PCIE LTR max snoop Latency 4
+ Offset(172), PML5, 16, // Offset(172), PCIE LTR max snoop Latency 5
+ Offset(174), PML6, 16, // Offset(174), PCIE LTR max snoop Latency 6
+ Offset(176), PML7, 16, // Offset(176), PCIE LTR max snoop Latency 7
+ Offset(178), PML8, 16, // Offset(178), PCIE LTR max snoop Latency 8
+ Offset(180), PML9, 16, // Offset(180), PCIE LTR max snoop Latency 9
+ Offset(182), PMLA, 16, // Offset(182), PCIE LTR max snoop Latency 10
+ Offset(184), PMLB, 16, // Offset(184), PCIE LTR max snoop Latency 11
+ Offset(186), PMLC, 16, // Offset(186), PCIE LTR max snoop Latency 12
+ Offset(188), PMLD, 16, // Offset(188), PCIE LTR max snoop Latency 13
+ Offset(190), PMLE, 16, // Offset(190), PCIE LTR max snoop Latency 14
+ Offset(192), PMLF, 16, // Offset(192), PCIE LTR max snoop Latency 15
+ Offset(194), PMLG, 16, // Offset(194), PCIE LTR max snoop Latency 16
+ Offset(196), PMLH, 16, // Offset(196), PCIE LTR max snoop Latency 17
+ Offset(198), PMLI, 16, // Offset(198), PCIE LTR max snoop Latency 18
+ Offset(200), PMLJ, 16, // Offset(200), PCIE LTR max snoop Latency 19
+ Offset(202), PMLK, 16, // Offset(202), PCIE LTR max snoop Latency 20
+ Offset(204), PMLL, 16, // Offset(204), PCIE LTR max snoop Latency 21
+ Offset(206), PMLM, 16, // Offset(206), PCIE LTR max snoop Latency 22
+ Offset(208), PMLN, 16, // Offset(208), PCIE LTR max snoop Latency 23
+ Offset(210), PMLO, 16, // Offset(210), PCIE LTR max snoop Latency 24
+ Offset(212), PNL1, 16, // Offset(212), PCIE LTR max no snoop Latency 1
+ Offset(214), PNL2, 16, // Offset(214), PCIE LTR max no snoop Latency 2
+ Offset(216), PNL3, 16, // Offset(216), PCIE LTR max no snoop Latency 3
+ Offset(218), PNL4, 16, // Offset(218), PCIE LTR max no snoop Latency 4
+ Offset(220), PNL5, 16, // Offset(220), PCIE LTR max no snoop Latency 5
+ Offset(222), PNL6, 16, // Offset(222), PCIE LTR max no snoop Latency 6
+ Offset(224), PNL7, 16, // Offset(224), PCIE LTR max no snoop Latency 7
+ Offset(226), PNL8, 16, // Offset(226), PCIE LTR max no snoop Latency 8
+ Offset(228), PNL9, 16, // Offset(228), PCIE LTR max no snoop Latency 9
+ Offset(230), PNLA, 16, // Offset(230), PCIE LTR max no snoop Latency 10
+ Offset(232), PNLB, 16, // Offset(232), PCIE LTR max no snoop Latency 11
+ Offset(234), PNLC, 16, // Offset(234), PCIE LTR max no snoop Latency 12
+ Offset(236), PNLD, 16, // Offset(236), PCIE LTR max no snoop Latency 13
+ Offset(238), PNLE, 16, // Offset(238), PCIE LTR max no snoop Latency 14
+ Offset(240), PNLF, 16, // Offset(240), PCIE LTR max no snoop Latency 15
+ Offset(242), PNLG, 16, // Offset(242), PCIE LTR max no snoop Latency 16
+ Offset(244), PNLH, 16, // Offset(244), PCIE LTR max no snoop Latency 17
+ Offset(246), PNLI, 16, // Offset(246), PCIE LTR max no snoop Latency 18
+ Offset(248), PNLJ, 16, // Offset(248), PCIE LTR max no snoop Latency 19
+ Offset(250), PNLK, 16, // Offset(250), PCIE LTR max no snoop Latency 20
+ Offset(252), PNLL, 16, // Offset(252), PCIE LTR max no snoop Latency 21
+ Offset(254), PNLM, 16, // Offset(254), PCIE LTR max no snoop Latency 22
+ Offset(256), PNLN, 16, // Offset(256), PCIE LTR max no snoop Latency 23
+ Offset(258), PNLO, 16, // Offset(258), PCIE LTR max no snoop Latency 24
+ Offset(260), U0C0, 32, // Offset(260), SerialIo Hidden UART0 BAR 0
+ Offset(264), U1C0, 32, // Offset(264), SerialIo Hidden UART1 BAR 0
+ Offset(268), XHPC, 8, // Offset(268), Number of HighSpeed ports implemented in XHCI controller
+ Offset(269), XRPC, 8, // Offset(269), Number of USBR ports implemented in XHCI controller
+ Offset(270), XSPC, 8, // Offset(270), Number of SuperSpeed ports implemented in XHCI controller
+ Offset(271), XSPA, 8, // Offset(271), Address of 1st SuperSpeed port
+ Offset(272), HPTB, 32, // Offset(272), HPET base address
+ Offset(276), HPTE, 8, // Offset(276), HPET enable
+ //SerialIo block
+ Offset(277), SMD0, 8, // Offset(277), SerialIo controller 0 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(278), SMD1, 8, // Offset(278), SerialIo controller 1 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(279), SMD2, 8, // Offset(279), SerialIo controller 2 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(280), SMD3, 8, // Offset(280), SerialIo controller 3 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(281), SMD4, 8, // Offset(281), SerialIo controller 4 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(282), SMD5, 8, // Offset(282), SerialIo controller 5 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(283), SMD6, 8, // Offset(283), SerialIo controller 6 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(284), SMD7, 8, // Offset(284), SerialIo controller 7 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(285), SMD8, 8, // Offset(285), SerialIo controller 8 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(286), SMD9, 8, // Offset(286), SerialIo controller 9 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(287), SMDA, 8, // Offset(287), SerialIo controller A mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(288), SIR0, 8, // Offset(288), SerialIo controller 0 irq number
+ Offset(289), SIR1, 8, // Offset(289), SerialIo controller 1 irq number
+ Offset(290), SIR2, 8, // Offset(290), SerialIo controller 2 irq number
+ Offset(291), SIR3, 8, // Offset(291), SerialIo controller 3 irq number
+ Offset(292), SIR4, 8, // Offset(292), SerialIo controller 4 irq number
+ Offset(293), SIR5, 8, // Offset(293), SerialIo controller 5 irq number
+ Offset(294), SIR6, 8, // Offset(294), SerialIo controller 6 irq number
+ Offset(295), SIR7, 8, // Offset(295), SerialIo controller 7 irq number
+ Offset(296), SIR8, 8, // Offset(296), SerialIo controller 8 irq number
+ Offset(297), SIR9, 8, // Offset(297), SerialIo controller 9 irq number
+ Offset(298), SIRA, 8, // Offset(298), SerialIo controller A irq number
+ Offset(299), SB00, 64, // Offset(299), SerialIo controller 0 BAR0
+ Offset(307), SB01, 64, // Offset(307), SerialIo controller 1 BAR0
+ Offset(315), SB02, 64, // Offset(315), SerialIo controller 2 BAR0
+ Offset(323), SB03, 64, // Offset(323), SerialIo controller 3 BAR0
+ Offset(331), SB04, 64, // Offset(331), SerialIo controller 4 BAR0
+ Offset(339), SB05, 64, // Offset(339), SerialIo controller 5 BAR0
+ Offset(347), SB06, 64, // Offset(347), SerialIo controller 6 BAR0
+ Offset(355), SB07, 64, // Offset(355), SerialIo controller 7 BAR0
+ Offset(363), SB08, 64, // Offset(363), SerialIo controller 8 BAR0
+ Offset(371), SB09, 64, // Offset(371), SerialIo controller 9 BAR0
+ Offset(379), SB0A, 64, // Offset(379), SerialIo controller A BAR0
+ Offset(387), SB10, 64, // Offset(387), SerialIo controller 0 BAR1
+ Offset(395), SB11, 64, // Offset(395), SerialIo controller 1 BAR1
+ Offset(403), SB12, 64, // Offset(403), SerialIo controller 2 BAR1
+ Offset(411), SB13, 64, // Offset(411), SerialIo controller 3 BAR1
+ Offset(419), SB14, 64, // Offset(419), SerialIo controller 4 BAR1
+ Offset(427), SB15, 64, // Offset(427), SerialIo controller 5 BAR1
+ Offset(435), SB16, 64, // Offset(435), SerialIo controller 6 BAR1
+ Offset(443), SB17, 64, // Offset(443), SerialIo controller 7 BAR1
+ Offset(451), SB18, 64, // Offset(451), SerialIo controller 8 BAR1
+ Offset(459), SB19, 64, // Offset(459), SerialIo controller 9 BAR1
+ Offset(467), SB1A, 64, // Offset(467), SerialIo controller A BAR1
+ //end of SerialIo block
+ Offset(475), GPEN, 8, // Offset(475), GPIO enabled
+ Offset(476), SGIR, 8, // Offset(476), GPIO IRQ
+ Offset(477), NIT1, 8, // Offset(477), RST PCIe Storage Cycle Router#1 Interface Type
+ Offset(478), NIT2, 8, // Offset(478), RST PCIe Storage Cycle Router#2 Interface Type
+ Offset(479), NIT3, 8, // Offset(479), RST PCIe Storage Cycle Router#3 Interface Type
+ Offset(480), NPM1, 8, // Offset(480), RST PCIe Storage Cycle Router#1 Power Management Capability Pointer
+ Offset(481), NPM2, 8, // Offset(481), RST PCIe Storage Cycle Router#2 Power Management Capability Pointer
+ Offset(482), NPM3, 8, // Offset(482), RST PCIe Storage Cycle Router#3 Power Management Capability Pointer
+ Offset(483), NPC1, 8, // Offset(483), RST PCIe Storage Cycle Router#1 PCIe Capabilities Pointer
+ Offset(484), NPC2, 8, // Offset(484), RST PCIe Storage Cycle Router#2 PCIe Capabilities Pointer
+ Offset(485), NPC3, 8, // Offset(485), RST PCIe Storage Cycle Router#3 PCIe Capabilities Pointer
+ Offset(486), NL11, 16, // Offset(486), RST PCIe Storage Cycle Router#1 L1SS Capability Pointer
+ Offset(488), NL12, 16, // Offset(488), RST PCIe Storage Cycle Router#2 L1SS Capability Pointer
+ Offset(490), NL13, 16, // Offset(490), RST PCIe Storage Cycle Router#3 L1SS Capability Pointer
+ Offset(492), ND21, 8, // Offset(492), RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data2
+ Offset(493), ND22, 8, // Offset(493), RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data2
+ Offset(494), ND23, 8, // Offset(494), RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data2
+ Offset(495), ND11, 32, // Offset(495), RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data1
+ Offset(499), ND12, 32, // Offset(499), RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data1
+ Offset(503), ND13, 32, // Offset(503), RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data1
+ Offset(507), NLR1, 16, // Offset(507), RST PCIe Storage Cycle Router#1 LTR Capability Pointer
+ Offset(509), NLR2, 16, // Offset(509), RST PCIe Storage Cycle Router#2 LTR Capability Pointer
+ Offset(511), NLR3, 16, // Offset(511), RST PCIe Storage Cycle Router#3 LTR Capability Pointer
+ Offset(513), NLD1, 32, // Offset(513), RST PCIe Storage Cycle Router#1 Endpoint LTR Data
+ Offset(517), NLD2, 32, // Offset(517), RST PCIe Storage Cycle Router#2 Endpoint LTR Data
+ Offset(521), NLD3, 32, // Offset(521), RST PCIe Storage Cycle Router#3 Endpoint LTR Data
+ Offset(525), NEA1, 16, // Offset(525), RST PCIe Storage Cycle Router#1 Endpoint LCTL Data
+ Offset(527), NEA2, 16, // Offset(527), RST PCIe Storage Cycle Router#2 Endpoint LCTL Data
+ Offset(529), NEA3, 16, // Offset(529), RST PCIe Storage Cycle Router#3 Endpoint LCTL Data
+ Offset(531), NEB1, 16, // Offset(531), RST PCIe Storage Cycle Router#1 Endpoint DCTL Data
+ Offset(533), NEB2, 16, // Offset(533), RST PCIe Storage Cycle Router#2 Endpoint DCTL Data
+ Offset(535), NEB3, 16, // Offset(535), RST PCIe Storage Cycle Router#3 Endpoint DCTL Data
+ Offset(537), NEC1, 16, // Offset(537), RST PCIe Storage Cycle Router#1 Endpoint DCTL2 Data
+ Offset(539), NEC2, 16, // Offset(539), RST PCIe Storage Cycle Router#2 Endpoint DCTL2 Data
+ Offset(541), NEC3, 16, // Offset(541), RST PCIe Storage Cycle Router#3 Endpoint DCTL2 Data
+ Offset(543), NRA1, 16, // Offset(543), RST PCIe Storage Cycle Router#1 RootPort DCTL2 Data
+ Offset(545), NRA2, 16, // Offset(545), RST PCIe Storage Cycle Router#2 RootPort DCTL2 Data
+ Offset(547), NRA3, 16, // Offset(547), RST PCIe Storage Cycle Router#3 RootPort DCTL2 Data
+ Offset(549), NMB1, 32, // Offset(549), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR
+ Offset(553), NMB2, 32, // Offset(553), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR
+ Offset(557), NMB3, 32, // Offset(557), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR
+ Offset(561), NMV1, 32, // Offset(561), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR value
+ Offset(565), NMV2, 32, // Offset(565), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR value
+ Offset(569), NMV3, 32, // Offset(569), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR value
+ Offset(573), NPB1, 32, // Offset(573), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR
+ Offset(577), NPB2, 32, // Offset(577), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR
+ Offset(581), NPB3, 32, // Offset(581), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR
+ Offset(585), NPV1, 32, // Offset(585), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR value
+ Offset(589), NPV2, 32, // Offset(589), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR value
+ Offset(593), NPV3, 32, // Offset(593), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR value
+ Offset(597), NRP1, 32, // Offset(597), RST PCIe Storage Cycle Router#1 Root Port number
+ Offset(601), NRP2, 32, // Offset(601), RST PCIe Storage Cycle Router#2 Root Port number
+ Offset(605), NRP3, 32, // Offset(605), RST PCIe Storage Cycle Router#3 Root Port number
+ Offset(609), , 8, // Offset(609), Flag indicating Exit Boot Service, to inform SMM
+ Offset(610), SXRB, 32, // Offset(610), Sx handler reserved MMIO base
+ Offset(614), SXRS, 32, // Offset(614), Sx handler reserved MMIO size
+ Offset(618), CIOE, 8, // Offset(618), Cio2 Device Enabled as ACPI device
+ Offset(619), CIOI, 8, // Offset(619), Cio2 Interrupt Number
+ Offset(620), TAEN, 8, // Offset(620), Thermal Device Acpi mode enabled
+ Offset(621), TIRQ, 8, // Offset(621), Thermal Device IRQ number
+ Offset(622), XWMB, 32, // Offset(622), XHCI memory base address
+ Offset(626), EMH4, 8, // Offset(626), eMMC HS400 mode enabled
+ Offset(627), EMDS, 8, // Offset(627), eMMC Driver Strength
+ Offset(628), CSKU, 8, // Offset(628), CPU SKU
+ Offset(629), ITA0, 16, // Offset(629),
+ Offset(631), ITA1, 16, // Offset(631),
+ Offset(633), ITA2, 16, // Offset(633),
+ Offset(635), ITA3, 16, // Offset(635),
+ Offset(637), ITS0, 8, // Offset(637),
+ Offset(638), ITS1, 8, // Offset(638),
+ Offset(639), ITS2, 8, // Offset(639),
+ Offset(640), ITS3, 8, // Offset(640),
+ Offset(641), PMBS, 16, // Offset(641), ACPI IO BASE address
+ Offset(643), PWRM, 32, // Offset(643), PWRM MEM BASE address
+ }
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl
new file mode 100644
index 0000000000..8628735184
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl
@@ -0,0 +1,214 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+
+ OperationRegion(PXCS,PCI_Config,0x00,0x480)
+ Field(PXCS,AnyAcc, NoLock, Preserve)
+ {
+ Offset(0),
+ VDID, 32,
+ Offset(0x50), // LCTL - Link Control Register
+ L0SE, 1, // 0, L0s Entry Enabled
+ , 3,
+ LDIS, 1,
+ , 3,
+ Offset(0x52), // LSTS - Link Status Register
+ , 13,
+ LASX, 1, // 0, Link Active Status
+ Offset(0x5A), // SLSTS[7:0] - Slot Status Register
+ ABPX, 1, // 0, Attention Button Pressed
+ , 2,
+ PDCX, 1, // 3, Presence Detect Changed
+ , 2,
+ PDSX, 1, // 6, Presence Detect State
+ , 1,
+ Offset(0x60), // RSTS - Root Status Register
+ , 16,
+ PSPX, 1, // 16, PME Status
+ Offset(0xA4),
+ D3HT, 2, // Power State
+ Offset(R_PCH_PCIE_MPC), // 0xD8, MPC - Miscellaneous Port Configuration Register
+ , 30,
+ HPEX, 1, // 30, Hot Plug SCI Enable
+ PMEX, 1, // 31, Power Management SCI Enable
+ Offset(R_PCH_PCIE_PCIEDBG), // 0x324
+ , 3,
+ LEDM, 1, // PCIEDBG.DMIL1EDM
+ }
+ Field(PXCS,AnyAcc, NoLock, WriteAsZeros)
+ {
+ Offset(R_PCH_PCIE_SMSCS), // 0xDC, SMSCS - SMI/SCI Status Register
+ , 30,
+ HPSX, 1, // 30, Hot Plug SCI Status
+ PMSX, 1 // 31, Power Management SCI Status
+ }
+
+
+ Name(LTRV, Package(){0,0,0,0})
+
+ //
+ // _DSM Device Specific Method
+ //
+ // Arg0: UUID Unique function identifier
+ // Arg1: Integer Revision Level
+ // Arg2: Integer Function Index (0 = Return Supported Functions)
+ // Arg3: Package Parameters
+ Method(_DSM, 4, Serialized) {
+ //
+ // Switch based on which unique function identifier was passed in
+ //
+ If (LEqual(Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
+ //
+ // _DSM Definitions for Latency Tolerance Reporting
+ //
+ // Arguments:
+ // Arg0: UUID: E5C937D0-3553-4d7a-9117-EA4D19C3434D
+ // Arg1: Revision ID: 2
+ // Arg2: Function Index: 1, 4 or 6
+ // Arg3: Empty Package
+ //
+ // Return:
+ // A Package of four integers corresponding with the LTR encoding defined
+ // in the PCI Express Base Specification, as follows:
+ // Integer 0: Maximum Snoop Latency Scale
+ // Integer 1: Maximum Snoop Latency Value
+ // Integer 2: Maximum No-Snoop Latency Scale
+ // Integer 3: Maximum No-Snoop Latency Value
+ // These values correspond directly to the LTR Extended Capability Structure
+ // fields described in the PCI Express Base Specification.
+ //
+ //
+ // Switch by function index
+ //
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index:0
+ // Standard query - A bitmask of functions supported
+ //
+ Case (0) {
+ Name(OPTS,Buffer(2){0,0})
+ CreateBitField(OPTS,0,FUN0)
+ CreateBitField(OPTS,4,FUN4)
+ CreateBitField(OPTS,6,FUN6)
+ CreateBitField(OPTS,8,FUN8)
+ CreateBitField(OPTS,9,FUN9)
+
+ if (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ Store(1,FUN0)
+ if (LTRE){
+ Store(1,Fun6)
+ }
+ if (OBFF){
+ Store(1,Fun4)
+ }
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)){ // test Arg1 for Revision ID: 3
+ Store(1,Fun8)
+ Store(1,Fun9)
+ }
+ }
+ }
+ Return (OPTS)
+ }
+ //
+ // Function Index: 4
+ //
+ Case(4) {
+ if (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ if (OBFZ){
+ Return (Buffer () {0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0}) // OBFF capable, offset 4[08h]
+ } else {
+ Return (Buffer () {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})
+ }
+ }
+ }
+ //
+ // Function Index: 5
+ // PCI FIRMWARE SPECIFICATION, REV. 3.2
+ // 4.6.5. _DSM for Ignoring PCI Boot Configurations
+ //
+ Case(5) {
+ If (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ return(1)
+ }
+ }
+ //
+ // Function Index: 6
+ // LTR Extended Capability Structure
+ //
+ Case(6) {
+ if (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ if (LTRZ){
+ if (LOr(LEqual(LMSL, 0),LEqual(LNSL, 0)))
+ {
+ if (LEqual (PCHS, SPTH)) {
+ Store (0x0846, LMSL)
+ Store (0x0846, LNSL)
+ } elseif (LEqual (PCHS, SPTL)) {
+ Store (0x1003, LMSL)
+ Store (0x1003, LNSL)
+ }
+ }
+ Store(And(ShiftRight(LMSL,10),7), Index(LTRV, 0))
+ Store(And(LMSL,0x3FF), Index(LTRV, 1))
+ Store(And(ShiftRight(LNSL,10),7), Index(LTRV, 2))
+ Store(And(LNSL,0x3FF), Index(LTRV, 3))
+
+ Return (LTRV)
+ } else {
+ Return (0)
+ }
+ }
+ }
+ Case(8) { //ECR ACPI additions for FW latency optimizations, DSM for Avoiding Power-On Reset Delay Duplication on Sx Resume
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)) { // test Arg1 for Revision ID: 3
+ return (1)
+ }
+ }
+ }
+ Case(9) { //ECR ACPI additions for FW latency optimizations, DSM for Specifying Device Readiness Durations
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)) { // test Arg1 for Revision ID: 3
+ return(Package(5){50000,Ones,Ones,50000,Ones})
+ }
+ }
+ }
+ } // End of switch(Arg2)
+ } // End of if
+ return (Buffer() {0x00})
+ } // End of _DSM
+
+ Device(PXSX)
+ {
+ Name(_ADR, 0x00000000)
+
+ // NOTE: Any PCIE Hot-Plug dependency for this port is
+ // specific to the CRB. Please modify the code based on
+ // your platform requirements.
+
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ }
+
+ //
+ // PCI_EXP_STS Handler for PCIE Root Port
+ //
+ Method(HPME,0,Serialized) {
+ If(LAnd(LNotEqual(VDID,0xFFFFFFFF), LEqual(PMSX,1))) { //if port exists and has PME SCI Status set...
+ Notify (PXSX, 0x2) //notify child device; this will cause its driver to clear PME_Status from device
+ Store(1,PMSX) // clear rootport's PME SCI status
+ Store(1,PSPX) // consume one pending PME notification to prevent it from blocking the queue
+ }
+ }
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl
new file mode 100644
index 0000000000..701cf6891a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl
@@ -0,0 +1,186 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#define PCI_CARD_BASE_ADDR0 0x10
+#define PCI_CARD_BASE_ADDR1 0x14
+#define PCI_CARD_BASE_ADDR2 0x18
+#define PCI_CARD_BASE_ADDR3 0x1C
+#define PCI_CARD_BASE_ADDR4 0x20
+#define PCI_CARD_BASE_ADDR5 0x24
+
+#define VDID_OFFSET 0x0 // 32bit value
+#define LEDM_OFFSET 0x324 // bit 3 - DMI L1 Entry Disable Mask (DMIL1EDM)
+#define LDIS_OFFSET 0x50 //bit 4 - Link Disable (LD)
+#define DPGE_OFFSET 0x420 // bit 30 - Disabled, Detect, L23_Rdy State and Un-Configured PHY Lane Power Gating Enable (DLSULPPGE)
+#define LASX_OFFSET 0x52 // bit 13 - Link Active (LA)
+
+#define ROOTPORT_READ 0
+#define ROOTPORT_WRITE 1
+#define ENDPOINT_READ 2
+#define ENDPOINT_WRITE 3
+
+ //RST Pcie Storage Remapped Base Address Index Value
+ Name(PRBI, 0)
+
+ //RST Pcie Storage Remapped Base Address Data Value
+ Name(PRBD, 0)
+
+ //RST Pcie Storage Endpoint Command Data
+ Name(PCMD, 0)
+
+ Name(RSTG, Package() { 0, 0, 0, 0 })
+ Name(PWRG, Package() { 0, 0, 0, 0 })
+ Name(SCLK, Package() { 0, 0, 0 })
+ //RST Pcie Storage Cycle Router
+ Name(NCRN, 0)
+
+ //
+ // Variables list to store corresponding value for different NVM device
+ //
+ Name(NITV, 0) // Interface Type
+ Name(NPMV, 0) // Power Management Capability Pointer
+ Name(NPCV, 0) // PCIe Capabilities Pointer
+ Name(NL1V, 0) // L1SS Capability Pointer
+ Name(ND2V, 0) // Endpoint L1SS Control Data2
+ Name(ND1V, 0) // Endpoint L1SS Control Data1
+ Name(NLRV, 0) // LTR Capability Pointer
+ Name(NLDV, 0) // Endpoint LTR Data
+ Name(NEAV, 0) // Endpoint LCTL Data
+ Name(NEBV, 0) // Endpoint DCTL Data
+ Name(NECV, 0) // Endpoint DCTL2 Data
+ Name(NRAV, 0) // RootPort DCTL2 Data
+ Name(NMBV, 0) // Endpoint unique MSI-X Table BAR
+ Name(NMVV, 0) // Endpoint unique MSI-X Table BAR value
+ Name(NPBV, 0) // Endpoint unique MSI-X PBA BAR
+ Name(NPVV, 0) // Endpoint unique MSI-X PBA BAR value
+ Name(NRPN, 0) // Assigned Root Port number
+
+ Name(MXIE, 0)
+
+ Name(ISD3, 0) // Is device in D3 state
+
+
+
+ //
+ // Restore of Remapped Device and Hidden Root Port
+ // This method is called after the endpoint is to be power ungated (D3-cold to D0 unitialized)
+ //
+ Method(CNRS, 0, Serialized)
+ {
+ Store("[ACPI RST] Restore Remapped Device and Hidden RP context |start", Debug)
+ ADBG(Concatenate("CNRSs ", ToDecimalString(Timer())))
+ //
+ // Return if RST Pcie Storage Remapping is disabled
+ //
+ If(LEqual(NITV,0))
+ {
+ Return()
+ }
+
+ //
+ // Clear all BARs in Remapped Device
+ //
+ RDCA(NCRN,PCI_CARD_BASE_ADDR0,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR1,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR2,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR3,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR4,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR5,0x0,0x0,ENDPOINT_WRITE)
+
+ //
+ // Restore remapped BAR and Endpoint CMD
+ //
+ RDCA(NCRN,PRBI,0x0,PRBD,ENDPOINT_WRITE)
+ RDCA(NCRN,0x4,0xFFFFFFF8,PCMD,ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device L1 Substate if this Capability is supported
+ //
+ If(LNotEqual(NL1V,0))
+ {
+ RDCA(NCRN,Add(NL1V,0x0C),0xFFFFFF00,ND2V,ENDPOINT_WRITE)
+ RDCA(NCRN,Add(NL1V,0x08),0x0000000F,And(ND1V,0xFFFFFFF0),ENDPOINT_WRITE)
+ RDCA(NCRN,Add(NL1V,0x08),0xFFFFFFFF,ND1V,ENDPOINT_WRITE)
+ }
+
+ //
+ // Restore of Remapped Device LTR if this Capability is supported
+ //
+ If(LNotEqual(NLRV,0))
+ {
+ RDCA(NCRN,Add(NLRV,0x04),0xFFFFFFFF,NLDV,ENDPOINT_WRITE)
+ }
+
+ //
+ // Restore of Remapped Device Link Control's "Enable Clock Power Management" field and "Common Clock Configuration" field
+ //
+ RDCA(NCRN,Add(NPCV,0x10),0xFFFFFEBF,And(NEAV,0xFFFC),ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device Device Control 2 field
+ //
+ RDCA(NCRN,Add(NPCV,0x28),0xFFFFFBFF,NECV,ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device Device Control field
+ //
+ RDCA(NCRN,Add(NPCV,0x8),0xFFFFFF1F,NEBV,ENDPOINT_WRITE)
+
+ //
+ // Restore of Hidden Root Port field
+ //
+ RDCA(NCRN,0x68,0xFFFFFBFF,NRAV,ROOTPORT_WRITE)
+
+ //
+ // Check CCC bit
+ // If this bit is 1, perform link retrain by setting the "Retrain Link" bit
+ //
+ If(LEqual(And(NEAV,0x40),0x40))
+ {
+ RDCA(NCRN,0x50,0xFFFFFFDF,0x20,ROOTPORT_WRITE)
+ //
+ // Poll PCIe Link Active status till it is active
+ //
+ ADBG(Concatenate("CNRSw ", ToDecimalString(Timer())))
+ while(LEqual(And(RDCA(NCRN,0x52,0x0,0x0,ROOTPORT_READ),0x2000),0))
+ {
+ Stall(10)
+ }
+ }
+ ADBG(Concatenate("CNRSx ", ToDecimalString(Timer())))
+
+ //
+ // Restore of Remapped Device Link Control's "Active State Link PM Control" field
+ //
+ RDCA(NCRN,Add(NPCV,0x10),0xFFFFFFFC,And(NEAV,0x0003),ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device related device BAR for the MSI-X Table BAR if the device supports unique MSI-X Table BAR
+ //
+ If(LNotEqual(NMVV,0))
+ {
+ RDCA(NCRN,NMBV,0x0,NMVV,ENDPOINT_WRITE)
+ }
+
+ //
+ // Restore of Remapped Device related device BAR for the MSI-X PBA BAR if the device supports unique MSI-X PBA BAR
+ //
+ If(LNotEqual(NPVV,0))
+ {
+ RDCA(NCRN,NPBV,0x0,NPVV,ENDPOINT_WRITE)
+ }
+
+ ADBG(Concatenate("CNRSe ", ToDecimalString(Timer())))
+ Store("[ACPI RST] Restore Remapped Device and Hidden RP context |complete", Debug)
+ }
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl
new file mode 100644
index 0000000000..d7f51f2b9b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl
@@ -0,0 +1,154 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#define ROOTPORT_READ 0
+#define ROOTPORT_WRITE 1
+#define ENDPOINT_READ 2
+#define ENDPOINT_WRITE 3
+#define GPIO_NO_CONTROL 0
+#define GPIO_INTERNAL 1
+#define GPIO_EXTERNAL 2
+#define EXPANDER0 0
+#define EXPENDER1 1
+#define INDEX_CONTROL 0
+#define INDEX_EXPANDER_NR 1
+#define INDEX_PIN_NR 2
+#define INDEX_POLARITY 3
+
+
+External(\_SB.PCI0.SAT0.NVM1.RAID, MethodObj)
+External(\_SB.PCI0.SAT0.NVM1.IR3E, MethodObj)
+External(\_SB.PCI0.SAT0.NVM1.VLPM)
+External(\_SB.PCI0.SAT0.NVM2.RAID, MethodObj)
+External(\_SB.PCI0.SAT0.NVM2.IR3E, MethodObj)
+External(\_SB.PCI0.SAT0.NVM2.VLPM)
+External(\_SB.PCI0.SAT0.NVM3.RAID, MethodObj)
+External(\_SB.PCI0.SAT0.NVM3.IR3E, MethodObj)
+External(\_SB.PCI0.SAT0.NVM3.VLPM)
+
+
+//
+// SDSM is Device Specific Method supporting AHCI DEVSLP
+// It is not guaranteed to be available on every boot
+//
+External(\_SB.PCI0.SAT0.SDSM, MethodObj)
+External(\_SB.PCI0.RP05.PWRG)
+External(\_SB.PCI0.RP05.RSTG)
+External(\_SB.PCI0.RP05.SCLK)
+External(\_SB.PCI0.RP09.PWRG)
+External(\_SB.PCI0.RP09.RSTG)
+External(\_SB.PCI0.RP09.SCLK)
+External(\_SB.PCI0.RP13.PWRG)
+External(\_SB.PCI0.RP13.RSTG)
+External(\_SB.PCI0.RP13.SCLK)
+External(\_SB.PCI0.RP17.PWRG)
+External(\_SB.PCI0.RP17.RSTG)
+External(\_SB.PCI0.RP17.SCLK)
+
+ // PCH SATA Controller
+ Device (SAT0)
+ {
+ //Bus 0x00, Device 0x17, Function 0x00
+ Name(_ADR, 0x00170000)
+
+ Method(_DSM,4,serialized){
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) };
+ if(CondRefOf(\_SB.PCI0.SAT0.SDSM)) { return (\_SB.PCI0.SAT0.SDSM(Arg0,Arg1,Arg2,Arg3)) };
+ Return(Buffer() {0})
+ }
+
+ Device(PRT0)
+ {
+ Name(_ADR,0x0000FFFF) // Port 0
+ }
+
+ Device(PRT1)
+ {
+ Name(_ADR,0x0001FFFF) // Port 1
+ }
+
+ Device(PRT2)
+ {
+ Name(_ADR,0x0002FFFF) // Port 2
+ }
+
+ Device(PRT3)
+ {
+ Name(_ADR,0x0003FFFF) // Port 3
+ }
+
+ Device(PRT4)
+ {
+ Name(_ADR,0x0004FFFF) // Port 4
+ }
+
+ Device(PRT5)
+ {
+ Name(_ADR,0x0005FFFF) // Port 5
+ }
+ Device(VOL0)
+ {
+ Name(_ADR,0x0080FFFF) // RST Raid Volume 0 or SRT Cache
+ }
+ Device(VOL1)
+ {
+ Name(_ADR,0x0081FFFF) // RST Raid Volume 1
+ }
+ Device(VOL2)
+ {
+ Name(_ADR,0x0082FFFF) // RST Raid Volume 2
+ }
+ // Asign Root Port Configuration for remapped drive.
+ // 4 arguments: NRPN, PWRG, RSTG, SCLK
+ Method(ARPC, 4, Serialized,,, {FieldUnitObj, PkgObj, PkgObj, PkgObj})
+ {
+ ADBG(Concatenate("NRPN: ", ToHexString(Arg0)))
+ Switch(ToInteger(Arg0))
+ {
+ Case(4)
+ {
+ if(condrefof(\_SB.PCI0.RP05.PWRG)) {CopyObject(\_SB.PCI0.RP05.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP05.RSTG)) {CopyObject(\_SB.PCI0.RP05.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP05.SCLK)) {CopyObject(\_SB.PCI0.RP05.SCLK,Arg3)}
+ }
+ Case(8)
+ {
+ if(condrefof(\_SB.PCI0.RP09.PWRG)) {CopyObject(\_SB.PCI0.RP09.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP09.RSTG)) {CopyObject(\_SB.PCI0.RP09.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP09.SCLK)) {CopyObject(\_SB.PCI0.RP09.SCLK,Arg3)}
+
+ }
+ Case(12)
+ {
+ if(condrefof(\_SB.PCI0.RP13.PWRG)) {CopyObject(\_SB.PCI0.RP13.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP13.RSTG)) {CopyObject(\_SB.PCI0.RP13.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP13.SCLK)) {CopyObject(\_SB.PCI0.RP13.SCLK,Arg3)}
+ }
+ Case(16)
+ {
+ if(condrefof(\_SB.PCI0.RP17.PWRG)) {CopyObject(\_SB.PCI0.RP17.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP17.RSTG)) {CopyObject(\_SB.PCI0.RP17.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP17.SCLK)) {CopyObject(\_SB.PCI0.RP17.SCLK,Arg3)}
+ }
+ Default
+ {
+ ADBG(Concatenate("ERR!NRPN: ", ToHexString(Arg0)))
+ }
+ }
+ }
+
+
+
+
+ }
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl
new file mode 100644
index 0000000000..808c73e06c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl
@@ -0,0 +1,247 @@
+/**@file
+ ACPI DSDT table for SCS Controllers
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+If(LEqual(PCHV(), SPTL)) { // SCS available on PCH-LP only
+
+Scope(\_SB.PCI0) {
+ //
+ // SCS eMMC (PCI Mode)
+ //
+ Device(PEMC) {
+ Name(_ADR, 0x001E0004)
+
+
+ // Memory Region to access to the eMMC PCI Configuration Space
+ OperationRegion(SCSR, PCI_Config, 0x00, 0x100)
+ Field(SCSR, WordAcc, NoLock, Preserve) {
+ Offset(R_PCH_SCS_DEV_PCS), // 0x84, PMCSR - Power Management Control and Status
+ PSTA,32,
+ Offset(R_PCH_SCS_DEV_PG_CONFIG), // 0xA2, Device PG config
+ , 2,
+ PGEN, 1 // [BIT2] PGE - PG Enable
+ }
+
+ Method(_PS0, 0, Serialized) {
+ Store(0, PGEN) // Disable PG
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRA(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0x7FFFFFBA) // Clear bits 31, 6, 2, 0
+ Sleep(2) // Wait 2ms
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRO(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0x80000045) // Set bits 31, 6, 2, 0
+
+ And(PSTA, 0xFFFFFFFC, PSTA) // Set BIT[1:0] = 00b - Power State D0
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ Method(_PS3, 0, Serialized) {
+ Store(1, PGEN) // Enable PG
+
+ Or(PSTA, 0x3, PSTA) // Set BIT[1:0] = 11b - Power State D3
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ // _DSM x86 Device Specific Method
+ // Arg0: UUID Unique function identifier
+ // Arg1: Integer Revision Level
+ // Arg2: Integer Function Index (0 = Return Supported Functions)
+ // Arg3: Package Parameters
+ Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ If(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ ADBG(Concatenate("EMH4=",ToDecimalString(EMH4)))
+ // Check the UUID
+ If(LEqual(Arg0, ToUUID("f6c13ea5-65cd-461f-ab7a-29f7e8d5bd61"))) {
+ // Check the revision
+ If(LGreaterEqual(Arg1, Zero)) {
+ //Switch statement based on the function index.
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index 0 the return value is a buffer containing
+ // one bit for each function index, starting with zero.
+ // Bit 0 - Indicates whether there is support for any functions other than function 0.
+ // Bit 1 - Indicates support to clear power control register
+ // Bit 2 - Indicates support to set power control register
+ // Bit 3 - Indicates support to set 1.8V signalling
+ // Bit 4 - Indicates support to set 3.3V signalling
+ // Bit 5 - Indicates support for HS200 mode
+ // Bit 6 - Indicates support for HS400 mode
+ // Bit 9 - Indicates eMMC I/O Driver Strength
+ //
+ // On SPT, for eMMC we have to support functions for
+ // HS200 and HS400 and I/O Driver Strength
+ //
+ Case(0) {
+ //
+ // The return value 0x261 (BIT6 set) for HS400 enabled and
+ // 0x221 (BIT6 not set) when HS400 is disabled in Setup menu.
+ //
+ If(LEqual(EMH4, 1)) {
+ Return(Buffer() {0x61, 0x02}) // HS400 support enabled
+ }
+ Return(Buffer() {0x21, 0x02}) // HS400 support disabled
+ }
+
+ //
+ // Function index 5 - corresponds to HS200 mode
+ // Return value from this function is used to program
+ // the UHS Mode Select bits in Host Control 2.
+ // 011b - corresponds to SDR104 and according to the
+ // SD Host Controller Spec and this value is overloaded
+ // to program the controller to select HS200 mode for eMMC.
+ //
+ Case(5) {
+ Return(Buffer() {0x3})
+ }
+
+ //
+ // Function index 6 - corresponds to HS400 mode
+ // Return value from this function is used to program
+ // the UHS Mode Select bits in Host Control 2.
+ // 101b is a reserved value according to the SD Host
+ // Controller Spec and we use this value for HS400 mode
+ // selection.
+ //
+ Case(6) {
+ Return(Buffer() {0x5})
+ }
+
+ //
+ // Function index 9 - corresponds to I/O Driver Strength
+ // Return value from this function represents the values
+ // of the Driver Strength selection
+ // (eMMC 5.01 Specification JESD84-B50.1, Table 186)
+ // that shall be programmed by the Host Driver (OS)
+ // as part of the Initialization flows.
+ //
+ Case(9) {
+ Switch(EMDS) {
+ Case(0x0) { Return(Buffer() {0x0}) } // 50 Ohm
+ Case(0x1) { Return(Buffer() {0x1}) } // 33 Ohm
+ Case(0x4) { Return(Buffer() {0x4}) } // 40 Ohm
+ }
+ }
+ } // End - Switch(Arg2)
+ }
+ } // End - UUID check
+ Return(Buffer() {0x0})
+ } // End - _DSM
+
+ Device (CARD) {
+ Name (_ADR, 0x00000008)
+ Method(_RMV, 0x0, NotSerialized) { Return (0) } // Device cannot be removed
+ }
+ } // Device(PEMC)
+
+ //
+ // SCS SD Card (PCI Mode)
+ //
+ Device(PSDC) {
+ Name(_ADR, 0x001E0006)
+
+
+ // Memory Region to access to the SDHC PCI Configuration Space
+ OperationRegion(SCSR, PCI_Config, 0x00, 0x100)
+ Field(SCSR, WordAcc, NoLock, Preserve) {
+ Offset(R_PCH_SCS_DEV_PCS), // 0x84, PMCSR - Power Management Control and Status
+ PSTA,32,
+ Offset(R_PCH_SCS_DEV_PG_CONFIG), // 0xA2, Device PG config
+ , 2,
+ PGEN, 1 // [BIT2] PGE - PG Enable
+ }
+
+ Method(_PS0, 0, Serialized) {
+ Store(0, PGEN) // Disable PG
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRA(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0xFFFFFE7A) // Clear bits 8, 7, 2, 0
+ Sleep(2) // Wait 2ms
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRO(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0x00000185) // Set bits 8, 7, 2, 0
+
+ And(PSTA, 0xFFFFFFFC, PSTA) // Set BIT[1:0] = 00b - Power State D0
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ Method(_PS3, 0, Serialized) {
+ Store(1, PGEN) // Enable PG
+
+ Or(PSTA, 0x3, PSTA) // Set BIT[1:0] = 11b - Power State D3
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ // _DSM x86 Device Specific Method
+ // Arg0: UUID Unique function identifier
+ // Arg1: Integer Revision Level
+ // Arg2: Integer Function Index (0 = Return Supported Functions)
+ // Arg3: Package Parameters
+ Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ If(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ // Check the UUID
+ If(LEqual(Arg0, ToUUID("f6c13ea5-65cd-461f-ab7a-29f7e8d5bd61"))) {
+ // Check the revision
+ If(LGreaterEqual(Arg1, Zero)) {
+ // Switch statement based on the function index.
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index 0 the return value is a buffer containing
+ // one bit for each function index, starting with zero.
+ // Bit 0 - Indicates whether there is support for any functions other than function 0.
+ // Bit 1 - Indicates support to clear power control register
+ // Bit 2 - Indicates support to set power control register
+ // Bit 3 - Indicates support to set 1.8V signalling
+ // Bit 4 - Indicates support to set 3.3V signalling
+ // Bit 5 - Indicates support for HS200 mode
+ // Bit 6 - Indicates support for HS400 mode
+ // Bit 9 - Indicates eMMC I/O Driver Strength
+ //
+ // On SPT, for SD we have to support functions to
+ // set 1.8V signalling and 3.3V signalling
+ //
+ Case(0) {
+ Return (Buffer() {0x19})
+ }
+
+ //
+ // Function Index 3: Set 1.8v signalling.
+ // We put a sleep of 100ms in this method to
+ // work around a known issue with detecting
+ // UHS SD card on SPT. This is to compensate
+ // for the SD VR slowness.
+ //
+ Case(3) {
+ Sleep (100) // Sleep 100ms
+ Return(Buffer(){0x00})
+ }
+
+ //
+ // Function Index 4: Set 3.3v signalling.
+ // We put a sleep of 100ms in this method to
+ // work around a known issue with detecting
+ // UHS SD card on SPT. This is to compensate
+ // for the SD VR slowness.
+ //
+ Case(4) {
+ Sleep (100) // Sleep 100ms
+ Return(Buffer(){0x00})
+ }
+ } // End - Switch(Arg2)
+ }
+ } // End - UUID check
+ Return(Buffer() {0x0})
+ } // End _DSM
+ }
+}
+
+}// End If(LEqual(PCHV(), SPTL)) - PCH-LP only
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl
new file mode 100644
index 0000000000..f33ee887e7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl
@@ -0,0 +1,749 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#define SERIAL_IO_PMECTRLSTATUS 0x84
+
+#define SERIAL_IO_DISABLED 0
+#define SERIAL_IO_ACPI 1
+#define SERIAL_IO_PCI 2
+#define SERIAL_IO_ACPIHIDDEN 3
+#define SERIAL_IO_LEGACY_UART 4
+
+#define KBL_GENERATION 2
+
+#define SERIAL_IO_SPT_LP_GPIO_HID "INT344B"
+#define SERIAL_IO_SPT_H_GPIO_HID "INT345D"
+#define SERIAL_IO_KBL_H_GPIO_HID "INT3451"
+
+#define SERIAL_IO_I2C0_HID "INT3442"
+#define SERIAL_IO_I2C1_HID "INT3443"
+#define SERIAL_IO_I2C2_HID "INT3444"
+#define SERIAL_IO_I2C3_HID "INT3445"
+#define SERIAL_IO_I2C4_HID "INT3446"
+#define SERIAL_IO_I2C5_HID "INT3447"
+#define SERIAL_IO_SPI0_HID "INT3440"
+#define SERIAL_IO_SPI1_HID "INT3441"
+#define SERIAL_IO_UART0_HID "INT3448"
+#define SERIAL_IO_UART1_HID "INT3449"
+#define SERIAL_IO_UART2_HID "INT344A"
+
+#define SERIAL_IO_I2C0_ADR 0x00150000
+#define SERIAL_IO_I2C1_ADR 0x00150001
+#define SERIAL_IO_I2C2_ADR 0x00150002
+#define SERIAL_IO_I2C3_ADR 0x00150003
+#define SERIAL_IO_I2C4_ADR 0x00190002
+#define SERIAL_IO_I2C5_ADR 0x00190001
+#define SERIAL_IO_SPI0_ADR 0x001E0002
+#define SERIAL_IO_SPI1_ADR 0x001E0003
+#define SERIAL_IO_UART0_ADR 0x001E0000
+#define SERIAL_IO_UART1_ADR 0x001E0001
+#define SERIAL_IO_UART2_ADR 0x00190000
+
+Scope(\_SB.PCI0) {
+
+
+ //
+ // Common code for D3 entry for all SerialIo devices including PCI mode
+ //
+ // @param[in] Arg0 PCI calculated address or ACPI BAR1 address of device to be put in D3
+ //
+ Method (LPD3, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,SERIAL_IO_PMECTRLSTATUS), 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { PMEC, 32 } //Note: SerialIO Does Not Support PME
+ Store(0x3, PMEC) // Set BIT[1:0] = 11b - Power State D3
+ Store(PMEC,TEMP) // perform a read to avoid ordering and noncoherency problems
+ }
+
+ //
+ // Common code for D0 entry for all SerialIo devices including PCI mode
+ //
+ // @param[in] Arg0 PCI calculated address or ACPI BAR1 address of device to be put in D0
+ //
+ Method (LPD0, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,SERIAL_IO_PMECTRLSTATUS), 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { PMEC, 32 } //Note: SerialIO Does Not Support PME
+ And(PMEC, 0xFFFF7FFC, PMEC) // Set BIT[1:0] = 00b - Power State D0
+ Store(PMEC,TEMP) // perform a read to avoid ordering and noncoherency problems
+ }
+
+ //
+ // Common code for retrieving hardware revision for all SerialIo devices
+ //
+ // @param[in] Arg0 BAR1 of device
+ //
+ // @retval Hardware Revison
+ //
+ Method (LHRV, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,0x8) , 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { HRV, 8 }
+ Return(HRV)
+ }
+
+ //
+ // Get D state of SerialIo device - for use in _PSC method
+ //
+ // @param[in] Arg0 PCI calculated address or ACPI BAR1 of device
+ //
+ // @retval D State
+ //
+ Method (GETD, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,SERIAL_IO_PMECTRLSTATUS) , 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { PMEC, 32 }
+ Return (And(PMEC, 0x3))
+ }
+
+ //
+ // Common code for reporting memory and interrupt resources for all SerialIo devices
+ //
+ // @param[in] Arg0 Device mode
+ // @param[in] Arg1 Memory address
+ // @param[in] Arg2 Interrupt number
+ //
+ // @retval Resource buffer
+ //
+ Method (LCRS, 3, Serialized) {
+ Name (RBUF, ResourceTemplate () {
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0)
+ Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , SIRQ) {20}
+ })
+ CreateDWordField(RBUF,BAR0._BAS,BVAL)
+ CreateDWordField(RBUF,BAR0._LEN,BLEN)
+ CreateDWordField(RBUF,SIRQ._INT,IRQN)
+ Store (Arg1, BVAL)
+ Store (Arg2, IRQN)
+ If(LEqual(Arg0,4)) {Store(8, BLEN)}
+ Return (RBUF)
+ }
+
+ //
+ // Common code for reporting status of all SerialIo devices
+ //
+ // @param[in] Arg0 Device's mode
+ //
+ // @retval 0 (do not show device) or 0xF (device is present)
+ //
+ Method (LSTA, 1, Serialized) {
+ If(LOr(LEqual(Arg0,0),LEqual(Arg0,3))) { Return(0) }
+ If(LLess(OSYS,2012)) { Return(0) } // OS older than Win8 = not supported
+ Return (0xF)
+ }
+
+ //
+ // Converts driver-visible GPIO number to interrupt number
+ //
+ // @param[in] Arg0 BAR1 of device
+ //
+ // @retval Interrupt number
+ //
+ Method (GIRQ,1,Serialized) {
+ Return (Add(24,Mod(Arg0,96)))
+ }
+
+} // END Scope(\_SB.PCI0)
+
+
+
+Scope(\_SB.PCI0) {
+ //
+ // An invisible device that claims memory resources reserved for SerialIo devices
+ // SerialIo devices in ACPI mode can't claim their BAR1 resources because these are aliases for PciCfg space
+ //
+ Device(SIRC) {
+ Name(_HID,EISAID("PNP0C02"))
+ Name(_STA,0x3) // device present and decodes its resources, but not to be displayed in OSPM
+ Name(_UID,5)
+
+ //
+ // Returns resource buffer with memory ranges used but not explicitely claimed by the device:
+ // in ACPI mode (SMDn=1) returns BAR1. In HIDDEN mode (SMDn=3) returns both BARs.
+ // In LegacyUART mode(SMDn=4) returns BAR1+ BAR0 except for first 8 bytes
+ //
+ // @param[in] Arg0 SMDn
+ // @param[in] Arg1 SB0n
+ // @param[in] Arg2 SB1n
+ //
+ // @retval Resource buffer with memory ranges
+ // if SMDn=0 (SERIAL_IO_DISABLED) or SMDn=2 (SERIAL_IO_PCI) returns an empty buffer
+ //
+ Method (ADDB, 3, Serialized) {
+
+ Name(BUFF,ResourceTemplate() { Memory32Fixed (ReadWrite, 0, 0x1000, BUF) })
+ CreateDWordField(BUFF, BUF._BAS, ADDR)
+ CreateDWordField(BUFF, BUF._LEN, LENG)
+
+ Store(ResourceTemplate() { }, Local0) // an empty buffer
+
+ If(LOr(LOr(LEqual(Arg0, SERIAL_IO_ACPI), LEqual(Arg0, SERIAL_IO_ACPIHIDDEN)), LEqual(Arg0, SERIAL_IO_LEGACY_UART))) {
+ Store(Arg2, ADDR)
+ ConcatenateResTemplate(Local0, BUFF, Local1) // add BAR1
+ Store(Local1, Local0)
+ }
+
+ If(LEqual(Arg0,SERIAL_IO_ACPIHIDDEN)) {
+ Store(Arg1,ADDR)
+ ConcatenateResTemplate(Local0, BUFF, Local1) // add BAR0
+ Store(Local1, Local0)
+ }
+
+ If(LEqual(Arg0, SERIAL_IO_LEGACY_UART)) {
+ Store(Add(8, Arg1), ADDR)
+ Store(0xFF8, LENG)
+ ConcatenateResTemplate(Local0, BUFF, Local1) // add BAR0 without 8 bytes
+ Store(Local1, Local0)
+ }
+ Return (Local0)
+ }
+
+ Method (_CRS, 0x0, Serialized) {
+ Store(ResourceTemplate() { }, Local0) // placeholder for concatenated buffers
+ //
+ // SB1[X] if device is configured as ACPI represents BAR1
+ // in case of PCI it stands for memory mapped BDF
+ //
+ ConcatenateResTemplate(Local0, ADDB(SMD0,SB00,SB10), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD1,SB01,SB11), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD2,SB02,SB12), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD3,SB03,SB13), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD4,SB04,SB14), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD5,SB05,SB15), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD6,SB06,SB16), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD7,SB07,SB17), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD8,SB08,SB18), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD9,SB09,SB19), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMDA,SB0A,SB1A), Local1)
+ Store(Local1, Local0)
+ //
+ // GPIO device always exists in chipset. If it's not visible in ACPI
+ // and doesn't claim its resources, declare it here to prevent OS from reusing its mem addresses
+ //
+ If(LEqual(\_SB.PCI0.GPI0._STA(),0)) {
+ ConcatenateResTemplate(Local0, \_SB.PCI0.GPI0._CRS(), Local1)
+ Store(Local1, Local0)
+ }
+ Return (Local0)
+ } // END _CRS
+ } // END Device(SIRC)
+
+ //----------------------------
+ // Serial IO GPIO Controller
+ //----------------------------
+ Device (GPI0)
+ {
+ Method (_HID) {
+ // Return HID based on PCH Product
+ If (LEqual(PCHV, SPTH)) {
+ If (LEqual(PCHG, KBL_GENERATION)) { Return(SERIAL_IO_KBL_H_GPIO_HID) }
+ Return(SERIAL_IO_SPT_H_GPIO_HID)
+ }
+ Return(SERIAL_IO_SPT_LP_GPIO_HID)
+ }
+
+ Name (LINK,"\\_SB.PCI0.GPI0")
+
+ Method (_CRS, 0x0, NotSerialized) {
+ Name (RBUF, ResourceTemplate () {
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00010000, BAR0)
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00010000, BAR1)
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00010000, BAR3)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , IRQ) { 14 } //Interrupt IRQ_EN
+ })
+ CreateDWordField(RBUF,BAR0._BAS,COM0)
+ CreateDWordField(RBUF,BAR1._BAS,COM1)
+ CreateDWordField(RBUF,IRQ._INT,IRQN)
+ Store( Add(SBRG,PCH_GPIO_COM0), COM0)
+ Store( Add(SBRG,PCH_GPIO_COM1), COM1)
+ CreateDWordField(RBUF,BAR3._BAS,COM3)
+ Store( Add(SBRG,PCH_GPIO_COM3), COM3)
+ Store(SGIR,IRQN)
+ Return (RBUF)
+ }
+
+ Method (_STA, 0x0, NotSerialized) {
+ If(LEqual(SBRG, 0)) { Return(0x0) } // has BAR for this device been programmed by the OS?
+ If(LEqual(GPEN, 0)) { Return(0x0) } // GPIO disabled in platform policy
+ Return(0xF)
+ }
+ }
+
+} // END Scope(\_SB.PCI0)
+
+
+//------------------------------------------
+// Serial IO I2C Controller 0 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C0) {
+ Name (LINK,"\\_SB.PCI0.I2C0") // Support for Windows 7
+ //
+ // I2C0 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB10))
+ }
+ Method (_PS0) {
+ LPD0(SB10)
+ }
+ Method (_PS3) {
+ LPD3(SB10)
+ }
+
+ //
+ // Apllies for I2C0 all modes except PCI
+ //
+ If(LNotEqual(SMD0,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C0_HID)
+ Method (_HRV) { Return (LHRV(SB10)) }
+ Method (_CRS) { Return (LCRS(SMD0,SB00,SIR0)) }
+ Method (_STA) { Return (LSTA(SMD0)) }
+ }
+
+ //
+ // Apllies for I2C0 PCI mode only
+ //
+ If(LEqual(SMD0,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C0_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C0)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 1 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C1) {
+ Name (LINK,"\\_SB.PCI0.I2C1") // Support for Windows 7
+ //
+ // I2C1 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB11))
+ }
+ Method (_PS0) {
+ LPD0(SB11)
+ }
+ Method (_PS3) {
+ LPD3(SB11)
+ }
+
+ //
+ // Apllies for I2C1 all modes except PCI
+ //
+ If(LNotEqual(SMD1,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C1_HID)
+ Method (_HRV) { Return (LHRV(SB11)) }
+ Method (_CRS) { Return (LCRS(SMD1,SB01,SIR1)) }
+ Method (_STA) { Return (LSTA(SMD1)) }
+ }
+
+ //
+ // Apllies for I2C1 PCI mode only
+ //
+ If(LEqual(SMD1,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C1_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C1)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 2 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C2) {
+ Name (LINK,"\\_SB.PCI0.I2C2") // Support for Windows 7
+ //
+ // I2C2 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB12))
+ }
+ Method (_PS0) {
+ LPD0(SB12)
+ }
+ Method (_PS3) {
+ LPD3(SB12)
+ }
+
+ //
+ // Apllies for I2C2 all modes except PCI
+ //
+ If(LNotEqual(SMD2,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C2_HID)
+ Method (_HRV) { Return (LHRV(SB12)) }
+ Method (_CRS) { Return (LCRS(SMD2,SB02,SIR2)) }
+ Method (_STA) { Return (LSTA(SMD2)) }
+ }
+
+ //
+ // Apllies for I2C2 PCI mode only
+ //
+ If(LEqual(SMD2,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C2_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C2)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 3 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C3) {
+ Name (LINK,"\\_SB.PCI0.I2C3") // Windows 7 W/A
+ //
+ // I2C3 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB13))
+ }
+ Method (_PS0) {
+ LPD0(SB13)
+ }
+ Method (_PS3) {
+ LPD3(SB13)
+ }
+
+ //
+ // Apllies for I2C3 all modes except PCI
+ //
+ If(LNotEqual(SMD3,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C3_HID)
+ Method (_HRV) { Return (LHRV(SB13)) }
+ Method (_CRS) { Return (LCRS(SMD3,SB03,SIR3)) }
+ Method (_STA) { Return (LSTA(SMD3)) }
+ }
+
+ //
+ // Apllies for I2C3 PCI mode only
+ //
+ If(LEqual(SMD3,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C3_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C3)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 4 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C4) {
+ Name (LINK,"\\_SB.PCI0.I2C4") // Support for Windows 7
+ //
+ // I2C4 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB14))
+ }
+ Method (_PS0) {
+ LPD0(SB14)
+ }
+ Method (_PS3) {
+ LPD3(SB14)
+ }
+
+ //
+ // Apllies for I2C4 all modes except PCI
+ //
+ If(LNotEqual(SMD4,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C4_HID)
+ Method (_HRV) { Return (LHRV(SB14)) }
+ Method (_CRS) { Return (LCRS(SMD4,SB04,SIR4)) }
+ Method (_STA) { Return (LSTA(SMD4)) }
+ }
+
+ //
+ // Apllies for I2C4 PCI mode only
+ //
+ If(LEqual(SMD4,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C4_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C4)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 5 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C5) {
+ Name (LINK,"\\_SB.PCI0.I2C5") // Support for Windows 7
+ //
+ // I2C5 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB15))
+ }
+ Method (_PS0) {
+ LPD0(SB15)
+ }
+ Method (_PS3) {
+ LPD3(SB15)
+ }
+
+ //
+ // Apllies for I2C5 all modes except PCI
+ //
+ If(LNotEqual(SMD5,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C5_HID)
+ Method (_HRV) { Return (LHRV(SB15)) }
+ Method (_CRS) { Return (LCRS(SMD5,SB05,SIR5)) }
+ Method (_STA) { Return (LSTA(SMD5)) }
+ }
+
+ //
+ // Apllies for I2C5 PCI mode only
+ //
+ If(LEqual(SMD5,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C5_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C5)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO SPI Controller 0 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (SPI0) {
+ //
+ // SPI0 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB16))
+ }
+ Method (_PS0) {
+ LPD0(SB16)
+ }
+ Method (_PS3) {
+ LPD3(SB16)
+ }
+
+ //
+ // Apllies for SPI0 all modes except PCI
+ //
+ If(LNotEqual(SMD6,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_SPI0_HID)
+ Method (_HRV) { Return (LHRV(SB16)) }
+ Method (_CRS) { Return (LCRS(SMD6,SB06,SIR6)) }
+ Method (_STA) { Return (LSTA(SMD6)) }
+ }
+
+ //
+ // Apllies for SPI0 PCI mode only
+ //
+ If(LEqual(SMD6,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_SPI0_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (SPI0)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO SPI Controller 1 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (SPI1) {
+ //
+ // SPI1 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD (SB17))
+ }
+ Method (_PS0) {
+ LPD0(SB17)
+ }
+ Method (_PS3) {
+ LPD3(SB17)
+ }
+
+ //
+ // Apllies for SPI0 all modes except PCI
+ //
+ If(LNotEqual(SMD7,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_SPI1_HID)
+ Method (_HRV) { Return (LHRV(SB17)) }
+ Method (_CRS) { Return (LCRS(SMD7,SB07,SIR7)) }
+ Method (_STA) { Return (LSTA(SMD7)) }
+ }
+
+ //
+ // Apllies for SPI1 PCI mode only
+ //
+ If(LEqual(SMD7,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_SPI1_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (SPI1)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO UART Controller 0 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (UA00) {
+
+ //
+ // Apllies for UART0 all modes except PCI
+ //
+ If(LNotEqual(SMD8,SERIAL_IO_PCI)) {
+ Method(_HID) {
+ If(LEqual(SMD8,SERIAL_IO_LEGACY_UART)) { Return (EISAID("PNP0C02")) }
+ Else { Return (SERIAL_IO_UART0_HID) }
+ }
+ Name (_UID, "SerialIoUart0")
+ Name (_DDN, "SerialIoUart0")
+ Method (_HRV) { Return (LHRV(SB18)) }
+ Method (_CRS) { Return (LCRS(SMD8,SB08,SIR8)) }
+ Method (_STA) { Return (LSTA(SMD8)) }
+ }
+
+ //
+ // Apllies for UART0 PCI mode only
+ //
+ If(LEqual(SMD8,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_UART0_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // UART0 PCI/ACPI PS0 PS3 and PSC
+ //
+ If(LNotEqual(SMD8,SERIAL_IO_LEGACY_UART)) {
+ Method (_PSC) {
+ Return (GETD (SB18))
+ }
+ Method (_PS0) {
+ LPD0(SB18)
+ }
+ Method (_PS3) {
+ LPD3(SB18)
+ }
+ }
+
+ } // Device (UA00)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO UART Controller 1 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (UA01) {
+
+ //
+ // Apllies for UART1 all modes except PCI
+ //
+ If(LNotEqual(SMD9,SERIAL_IO_PCI)) {
+ Method(_HID) {
+ If(LEqual(SMD9,SERIAL_IO_LEGACY_UART)) { Return (EISAID("PNP0C02")) }
+ Else { Return (SERIAL_IO_UART1_HID) }
+ }
+ Name (_UID, "SerialIoUart1")
+ Name (_DDN, "SerialIoUart1")
+ Method (_HRV) { Return (LHRV(SB19)) }
+ Method (_CRS) { Return (LCRS(SMD9,SB09,SIR9)) }
+ Method (_STA) { Return (LSTA(SMD9)) }
+ }
+
+ //
+ // Apllies for UART1 PCI mode only
+ //
+ If(LEqual(SMD9,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_UART1_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // UART1 PCI/ACPI PS0 PS3 and PSC
+ //
+ If(LNotEqual(SMD9,SERIAL_IO_LEGACY_UART)) {
+ Method (_PSC) {
+ Return (GETD (SB19))
+ }
+ Method (_PS0) {
+ LPD0(SB19)
+ }
+ Method (_PS3) {
+ LPD3(SB19)
+ }
+ }
+
+ } // Device (UA01)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO UART Controller 2 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (UA02) {
+
+ //
+ // Apllies for UART2 all modes except PCI
+ //
+ If(LNotEqual(SMDA,SERIAL_IO_PCI)) {
+ Method (_HID) {
+ If(LEqual(SMDA,SERIAL_IO_LEGACY_UART)) { Return (EISAID("PNP0C02")) }
+ Else { Return (SERIAL_IO_UART2_HID) }
+ }
+ Name (_UID, "SerialIoUart2")
+ Name (_DDN, "SerialIoUart2")
+ Method (_HRV) { Return (LHRV(SB1A)) }
+ Method (_CRS) { Return (LCRS(SMDA,SB0A,SIRA)) }
+ Method (_STA) { Return (LSTA(SMDA)) }
+ }
+
+ //
+ // Apllies for UART2 PCI mode only
+ //
+ If(LEqual(SMDA,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_UART2_ADR)
+ Method (_DSM,4,Serialized){if(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // UART2 PCI/ACPI PS0 PS3 and PSC excluding Legacy Uart
+ //
+ If(LNotEqual(SMDA,SERIAL_IO_LEGACY_UART)) {
+ Method (_PSC) {
+ Return (GETD(SB1A))
+ }
+ Method (_PS0) {
+ LPD0(SB1A)
+ }
+ Method (_PS3) {
+ LPD3(SB1A)
+ }
+ }
+
+ } // Device (UA02)
+} // Scope(\_SB.PCI0)
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl
new file mode 100644
index 0000000000..54c1242178
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl
@@ -0,0 +1,310 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+External(\_SB.PCI0.LPCB.H_EC.XDAT, MethodObj)
+
+Scope(\_SB.PCI0)
+{
+ Device(XDCI)
+ {
+ Name (_ADR, 0x00140001) // _ADR: Address
+
+ OperationRegion (OTGD, PCI_Config, 0x0, 0x100)
+ Field (OTGD, DWordAcc, NoLock, Preserve)
+ {
+ Offset(0x0),
+ DVID, 16,
+ Offset(0x10),
+ XDCB, 64
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field (OTGD, ByteAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_PMCSR), // 0x84, PM_CS - Power Management Control/Status
+ D0I3, 2, // PM_CS[1:0] PowerState
+ , 6,
+ PMEE, 1, // bit 8, PME Enable
+ , 6,
+ PMES, 1 // bit 15, PME Status
+ }
+
+ Method(XDBA, 0)
+ {
+ Return(And(^XDCB, 0xFFFFFFFFFFFFFF00))
+ }
+
+ //
+ // Arg0: UUID = {732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511}
+ // Arg1: Revision ID = 1
+ // Arg2: Function Index
+ // Arg3: Argument
+ //
+ Method(_DSM,4,Serialized)
+ {
+ If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ If(LEqual(Arg0, ToUUID("732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"))){
+ If(Lequal(Arg1, 1)){
+ //
+ // Set PMU Power State
+ // Arg0: 0x00 PMU should enter the D0 power state.
+ // 0x03 PMU should enter the D3 power state.
+ // Arg1: 0x03 Enable PMU PME
+ // 0x00 Clear PMU PME
+ //
+ Method (SPPS,2,Serialized) {
+ OperationRegion(XDBW, SystemMemory, XDBA(), 0x110000)
+ Field(XDBW, WordAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG2), // 0x10F810
+ , 8,
+ U2CP, 2, // USB2 core power state
+ U3CP, 2, // USB3 core power state
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG4), // 0x10F818
+ PUPS, 2, // PMU power state
+ , 1,
+ PURC, 1, // Reset PMU core
+ , 12,
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG5), // 0x10F81C
+ , 3,
+ UXPE, 2, // U2 PME EN / U3 PME EN
+ , 11,
+ }
+
+ // Local 1 is power state D0 or D3
+ Store(Arg0, Local1)
+ // Local 2 is Enable/Clear PMU PME
+ Store(Arg1, Local2)
+
+ If(LEqual(Local1, 0)){
+ // Clear PMU PME
+ // 0x10F81C BIT3: USB3 PME
+ // 0x10F81C BIT4: USB2 PME
+ Store(0, UXPE)
+ // Wait for at least 100us, currently configured to 1000us
+ Store(0, Local0)
+ While(LLess(Local0, 10)){
+ Stall(100)
+ Increment(Local0)
+ }
+ // Set PMU to D0 by writing 0 to 0x10f818 Bit 1:0
+ Store(0, PUPS)
+ // Wait 200ms for PMU to enter D0
+ // Confirm PMU being in D0 by checking 0x10f810 Bit 11:8 to be clear
+ // 0x10f810 Bit 11:10 - Current power state of USB3 core
+ // 0x10f810 Bit 9:8 - Current power state of USB2 core
+ // both should be clear
+ Store(0,Local0)
+ While(LLess(Local0,2000)){
+ Stall(100)
+ If(LAnd(LEqual(U2CP,0),LEqual(U3CP,0))){
+ break
+ }
+ Increment(Local0)
+ }
+ If(LNotEqual(U2CP, 0)){
+ // Show warning message
+ }
+ If(LNotEqual(U3CP, 0)){
+ // Show warning message
+ }
+ Return(0)
+ }
+
+ If(LEqual(Local1, 3)){
+ // PMU should be in D0 at this point
+ // 0x10f810 Bit 11:10 - current power state of USB3 core
+ // 0x10f810 Bit 9:8 - current power state of USB2 core
+ // both should be clear
+ If(LNotEqual(U2CP, 0)){
+ // Show warning message
+ }
+ If(LNotEqual(U3CP, 0)){
+ // Show warning message
+ }
+ // Set PMU to D3 by writing 3 to 0x10f818 bit 1:0
+ Store(3, PUPS)
+ // Wait 200ms for PMU to enter D3
+ // Confirm PMU being in D3 by checking 0x10f810 Bit 11:8 to be set
+ // 0x10f810 Bit 11:10 - Current power state of USB3 core
+ // 0x10f810 Bit 9:8 - Current power state of USB2 core
+ // both should be set
+ Store(0,Local0)
+ While(LLess(Local0,2000)){
+ Stall(100)
+ If(LAnd(LEqual(U2CP,3),LEqual(U3CP,3))){
+ break
+ }
+ Increment(Local0)
+ }
+ If(LNotEqual(U2CP, 3)){
+ // Show warning message
+ }
+ If(LNotEqual(U3CP, 3)){
+ // Show warning message
+ }
+ // Set/Clear PMU PME
+ // 0x10F81C BIT3: USB3 PME
+ // 0x10F81C BIT4: USB2 PME
+ Store(Local2, UXPE)
+ Return(0)
+ }
+ Return(0)
+ }
+
+ Switch(ToInteger(Arg2)) {
+ Case(0){
+ // Function 0: return Bit map to indicate Function 0,1,4,5,6,7 supported
+ Return(Buffer(){0xF3})
+ }
+ Case(1){
+ // Function 1: Attach/Detach and Port Detection Properties Method
+ // This method is called by the USB function stack to set the power state of the PMU.
+ // Bit 0 as 1: to indicate Platform support for Attach/detach notify
+ // Bit 1 as 0:HW based charging indication
+ Return(0x1)
+ }
+ Case(4){
+ // Function 4: Set PMU Power State Method, clear PMU PME
+ // Arg3: A package consisting of 1 ULONG value
+ // 0x00 PMU should enter the D0 power state.
+ // 0x03 PMU should enter the D3 power state.
+
+ // Local 1 is power state D0 or D3
+ Store(DerefOf(Index(Arg3,0)), Local1)
+
+ // Set PMU to Dx state and clear PMU PME
+ SPPS(Local1, 0)
+ }
+ Case(5){
+ // Function 5: Attach Notification Enabled Method
+ // This method is called by the USB function stack to indicate that it has enabled ACPI attach detach notifications.
+ // In response the platform may issue an notification indicating the current attach/detach state of the controller.
+
+ // If device is attached, notify XDCI with 0x80
+ // If device is detached, notify XDCI with 0x81
+
+
+ If(CondRefOf(\_SB.PCI0.LPCB.H_EC.XDAT)){
+ If(LEqual(\_SB.PCI0.LPCB.H_EC.XDAT(), 1)){
+ Notify(\_SB.PCI0.XDCI,0x80)
+ }Else{
+ Notify(\_SB.PCI0.XDCI,0x81)
+ }
+ }
+
+ Return(0)
+ }
+ Case(6){
+ // Function 6: XDCI Soft Reset Workaround
+ // Return value indicate to OS softreset should be done by OS or not
+ // Return value == 1: OS does softreset
+ // Return value == 0: platform does softreset
+
+
+ OperationRegion(XDBD, SystemMemory, XDBA(), 0x110000)
+ Field(XDBD, DwordAcc, NoLock, Preserve)
+ {
+ Offset(0xC704),
+ , 30,
+ CSFR, 1,
+ , 1,
+ }
+ OperationRegion(XDW2, SystemMemory, XDBA(), 0x110000)
+ Field(XDW2, WordAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG6), // 0x10F820
+ , 13,
+ OTHC, 1, // OTG switched to host complete
+ }
+
+ If(LEqual(OTHC, 0)){
+ Store(1, CSFR)
+ // timeout is 100ms
+ Store(0, Local0)
+ While(LLess(Local0, 100)){
+ If(LEqual(CSFR, 0)){
+ Break
+ }
+ Sleep(1)
+ }
+ }
+ Return(0)
+ }
+ Case(7){
+ // Function 7: Get PMU Power State Method
+ // Return:
+ // 0: PMU is in D0 state
+ // 3: PMU is in D3 state
+
+
+ OperationRegion(XD22, SystemMemory, XDBA(), 0x110000)
+ Field(XD22, WordAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG4), // 0x10F818
+ P2PS, 2, // PMU power state
+ , 14,
+ }
+ Store(P2PS, Local0)
+ Return(Local0)
+ }
+ }
+ }
+ }
+ Return(Buffer() {0})
+ }
+
+ Name (_DDN, "SPT XHCI controller") // _DDN: DOS Device Name
+ Name (_STR, Unicode ("SPT XHCI controller")) // _STR: Description String
+
+ Method(_S0W, 0)
+ { // PMEs can be generated from D3(hot)
+ Return(3)
+ }
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ If(LNotEqual(DVID, 0xFFFFFFFF)) { // device not disabled
+ Return (0xF)
+ } Else{
+ Return (0x0)
+ }
+ }
+
+ // XDCI Wake Support
+ Method(_PRW, 0)
+ {
+ Return(GPRW(0x6D,4)) // can wakeup from S4 state
+ }
+
+ Method(_DSW, 3)
+ {
+ Store(Arg0, PMEE)
+ }
+
+ Method(GPEH, 0, NotSerialized)
+ {
+ If(LEqual(DVID,0xFFFF)){
+ Return()
+ }
+ Store(PMES, Local0)
+ Store(1, PMES) // Clear PME Status
+ If(LAnd(PMEE, Local0)){
+ Notify(XDCI, 0x02)
+ }
+ }
+
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl
new file mode 100644
index 0000000000..873246f662
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl
@@ -0,0 +1,558 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+External(\_SB.PCI0.XHC.PS0X, MethodObj)
+External(\_SB.PCI0.XHC.PS3X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.PS0X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.PS2X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.PS3X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.INIR, MethodObj)
+
+Scope(\_SB_.PCI0) {
+ Device(XHC) {
+
+ Name(_ADR, 0x00140000)
+
+ OperationRegion(XPRT,PCI_Config,0x00,0x100)
+ Field(XPRT,AnyAcc,NoLock,Preserve)
+ {
+ DVID, 16,
+ Offset(0x10),
+ XADL, 32,
+ XADH, 32,
+ Offset(0x50), // XHCLKGTEN - Clock Gating
+ , 2,
+ STGE, 1, // Clock Gating Bit SSLTCGE
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field(XPRT,ByteAcc,NoLock,Preserve)
+ {
+ Offset(R_PCH_XHCI_PWR_CNTL_STS), // 0x74
+ D0D3, 2, // 0x74 BIT[1:0]
+ , 6,
+ PMEE, 1, // PME Enable
+ , 6,
+ PMES, 1, // PME Status
+ }
+
+ //
+ // Variable to store the maximum D state supported in S0.
+ //
+ Name (XFLT, 0)
+ //
+ // XHCI controller won't go into D3Hot during S0 until _DSM method is evaluated by filter driver.
+ //
+ Method(_DSM,4,serialized){
+ ADBG("_DSM")
+ ShiftLeft(XADH, 32, Local0)
+ Or (Local0, XADL, Local0)
+ And(Local0,0xFFFFFFFFFFFFFFF0,Local0)
+ OperationRegion(XMIO,SystemMemory,Local0,0x9000)
+ Field(XMIO,AnyAcc,Lock,Preserve)
+ {
+ Offset(R_PCH_LP_XHCI_PORTSC02USB3), // PORTSCXUSB3 - Port X Status and Control USB3
+ PCCS, 1, // Current Connect Status
+ , 4,
+ PPLS, 4, // Port Link Status
+ PTPP, 1, // Port Power
+ }
+
+ If(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+ //
+ // Check GUID ac340cb7-e901-45bf-b7e6-2b34ec931e23
+ //
+ If(LEqual(Arg0, Buffer(0x10) { 0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45, 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23 }))
+ {
+ //
+ // Only Supported value is "0x3"
+ //
+ If(LEqual(Arg1, 0x3))
+ {
+ Store(Arg1,XFLT)
+ }
+ }
+ Return(Buffer() {0})
+ }
+
+ Method(_S3D, 0, NotSerialized)
+ {
+ Return(3)
+ }
+ Method(_S4D, 0, NotSerialized)
+ {
+ Return(3)
+ }
+ Method(_S3W, 0, NotSerialized)
+ {
+ Return(3)
+ }
+ Method(_S4W, 0, NotSerialized)
+ {
+ Return(3)
+ }
+
+ //
+ // Once the filter driver is installed, D3 is allowed.
+ //
+ Method(_S0W, 0x0, NotSerialized)
+ {
+ If(LEqual(XFLT, Zero))
+ {
+ Return(0x0)
+ }
+ Else
+ {
+ Return(0x3)
+ }
+ }
+
+ Method(_PRW, 0)
+ {
+ Return(GPRW(0x6D, 4)) // can wakeup from S4 state
+ }
+
+ Method(_DSW, 3)
+ {
+ Store(Arg0, PMEE)
+ }
+
+ Method(_INI) {
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.INIR)) { // _INI for RTD3
+ \_SB.PCI0.XHC.RHUB.INIR()
+ }
+ }
+
+ //
+ // GPE handler for XHCI, this is part of _Lxx handler for bus 0 PME
+ //
+ Method(GPEH)
+ {
+ If(LEqual(DVID, 0xFFFF)) {
+ Return()
+ }
+ Store(PMES, Local0)
+ Store(1, PMES) // clear PME Status
+ If(LAnd(PMEE, Local0)) {
+ Notify(XHC, 0x02)
+ }
+ }
+
+ OperationRegion(XHCP, SystemMemory, Add(\_SB.PCI0.GPCB(), 0xA0000), 0x100)
+ Field(XHCP,AnyAcc,Lock,Preserve)
+ {
+ Offset(0x4),
+ PDBM, 16,
+ Offset(0x10),
+ MEMB, 64
+ }
+
+ //
+ // USRA (USbR port Address), method for calculating address of first USBR port in XHCI controller
+ //
+ Method(USRA,0,Serialized) {
+ If(LEqual(PCHV, SPTH)) { // SPT-H
+ Return (15)
+ } Else { // SPT-LP
+ Return (11)
+ }
+ }
+
+ //
+ // SSPA (SuperSpeed Port Address), method for calculating address of first SS port in XHCI controller
+ //
+ Method(SSPA,0,Serialized) {
+ If(LEqual(PCHV, SPTH)) { // SPT-H
+ Return (17)
+ } Else { // SPT-LP
+ Return (13)
+ }
+ }
+
+ Name(XRST, Zero)
+
+ Method(_PS0,0,Serialized)
+ {
+
+ If(LEqual(^DVID,0xFFFF))
+ {
+ Return()
+ }
+
+ Store(^MEMB,Local2) // Save MBAR
+ Store(^PDBM,Local1) // Save CMD
+
+ And(^PDBM,Not(0x06),^PDBM) // Clear MSE/BME
+ Store(0,STGE)
+
+ //
+ // Switch to D0
+ //
+ Store(0,^D0D3)
+
+ Store(\XWMB,^MEMB) // Set MBAR
+ Or(Local1,0x0002,^PDBM) // Set MSE
+
+ OperationRegion(MC11,SystemMemory,\XWMB,0x9000)
+ Field(MC11,DWordAcc,Lock,Preserve)
+ {
+ Offset(R_PCH_XHCI_USB2PMCTRL), // 0x81C4, USB2PMCTRL - USB2 Power Management Control
+ , 2,
+ UPSW, 2, // U2PSUSPGP
+ }
+
+ Store(0x0,UPSW)
+
+ And(^PDBM,Not(0x02),^PDBM) // Clear MSE
+
+ Store(Local2,^MEMB) // Restore MBAR
+ Store(Local1,^PDBM) // Restore CMD
+
+ //
+ // Call platform XHC PS0 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.PS0X))
+ {
+ \_SB.PCI0.XHC.PS0X()
+ }
+
+ //
+ //
+ If(LAnd(UWAB,LOr(LEqual(D0D3,0),LEqual(\_SB.PCI0.XDCI.D0I3,0)))) {
+ //
+ // If the USB WA Bit is set and any XHCI or XDCI controller is in D0
+ //
+ //
+ // USB2 PHPY Power Gating - SW WA
+ //
+ // 1. BIOS writes a new command to the MTPMC register to cause the PMC to disable power gating
+ Store(1,MPMC)
+
+ // 2. BIOS waits for PCH_PM_STS.MSG_FULL_STS to be 0
+ // In parallel and in response to the previous command from BIOS, PMC FW will:
+ // * Make the USB2 force common lane PG match the BIOS policy (common lane PG disallowed)
+ // * Disable SUS power gating in XHCI
+ // * Wait for USB2 PHY side_pok to be 1
+ // * Disable core power gating in USB2 PHY
+ // * Disable common lane power gating in USB2 PHY (probably not necessary, consider removal)
+ // * Wait for USB2 SUS restoration status to be set, and do USB2 SUS power gating restoration
+ // * Get the PHY in the correct state before allowing transition to D0.
+ // * Clear MSG_FULL_STS
+ // BIOS sees MSG_FULL_STS clear and exits the method
+ //
+ While(PMFS) {
+ Sleep(10)
+ }
+ } // End If(UWAB)
+
+ }
+
+ Method(_PS3,0,Serialized)
+ {
+
+ If(LEqual(^DVID,0xFFFF))
+ {
+ Return()
+ }
+
+ Store(^MEMB,Local2) // Save MBAR
+ Store(^PDBM,Local1) // Save CMD
+
+ And(^PDBM,Not(0x06),^PDBM) // Clear MSE/BME
+
+ //
+ // Switch back to D0
+ //
+ Store(0,^D0D3)
+
+ Store(\XWMB,^MEMB) // Set MBAR
+ Or(Local1,0x0002,^PDBM) // Set MSE
+
+ OperationRegion(MC11,SystemMemory,\XWMB,0x9000)
+ Field(MC11,DWordAcc,Lock,Preserve)
+ {
+ Offset(R_PCH_XHCI_USB2PMCTRL), // 0x81C4, USB2PMCTRL - USB2 Power Management Control
+ , 2,
+ UPSW, 2, // U2PSUSPGP
+ }
+
+ Store(0x3,UPSW)
+
+ And(^PDBM,Not(0x02),^PDBM) // Clear MSE
+
+ Store(1,STGE)
+
+ //
+ // Switch back to D3
+ //
+ Store(3,^D0D3)
+
+ Store(Local2,^MEMB) // Restore MBAR
+ Store(Local1,^PDBM) // Restore CMD
+
+ //
+ // Call platform XHC PS3 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.PS3X))
+ {
+ \_SB.PCI0.XHC.PS3X()
+ }
+
+ If(LAnd(UWAB,LAnd(LEqual(D0D3,3),LOr(LEqual(\_SB.PCI0.XDCI.D0I3,3),LEqual(\_SB.PCI0.XDCI.DVID,0xFFFF))))) {
+ //
+ // If the USB WA Bit is set and ((XHCI is in D3) AND ((XDCI is in D3) OR (XDCI is function disabled)))
+ //
+ // 1. BIOS writes a new command to the MTPMC register to enable power gating
+ Store(3,MPMC)
+
+ // 2. BIOS waits for PCH_PM_STS.MSG_FULL_STS to be 0
+ // In parallel and in response to the previous command from BIOS, PMC FW will:
+ // * Make the USB2 force common lane PG match the BIOS policy (common lane PG allowed)
+ // * Enable SUS power gating in XHCI
+ // * Enable core power gating in USB2 PHY
+ // * Enable common lane power gating in the USB2 PHY
+ // * Clear MSG_FULL_STS
+ // BIOS sees MSG_FULL_STS clear and exits the method
+ //
+ While(PMFS) {
+ Sleep(10)
+ }
+ } // End If(UWAB)
+ }
+
+ //
+ //
+ // Check for XHCI switch UUID
+ //
+ // Arguments:
+ // Arg0 (Buffer) : UUID
+ //
+ // Returns:
+ // 1: It's valid UUID
+ // 0: Invalid UUID
+ //
+ Method(CUID,1,Serialized) {
+ If(LEqual(Arg0,ToUUID("7c9512a9-1705-4cb4-af7d-506a2423ab71"))) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ Device(RHUB)
+ {
+ Name(_ADR, Zero)
+
+ // PS0 Method for xHCI Root Hub
+ Method(_PS0,0,Serialized)
+ {
+ If(LEqual(\_SB.PCI0.XHC.DVID,0xFFFF))
+ {
+ Return()
+ }
+ //
+ // Call platform XHC.RHUB PS0 method if present.
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.PS0X))
+ {
+ \_SB.PCI0.XHC.RHUB.PS0X()
+ }
+ }
+
+ // PS2 Method for xHCI Root Hub
+ Method(_PS2,0,Serialized)
+ {
+ If(LEqual(\_SB.PCI0.XHC.DVID,0xFFFF))
+ {
+ Return()
+ }
+ //
+ // Call platform XHC.RHUB PS2 method if present.
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.PS2X))
+ {
+ \_SB.PCI0.XHC.RHUB.PS2X()
+ }
+ }
+
+ // PS3 Method for xHCI Root Hub
+ Method(_PS3,0,Serialized)
+ {
+ If(LEqual(\_SB.PCI0.XHC.DVID,0xFFFF))
+ {
+ Return()
+ }
+ //
+ // Call platform XHC.RHUB PS3 method if present.
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.PS3X))
+ {
+ \_SB.PCI0.XHC.RHUB.PS3X()
+ }
+ }
+
+ //
+ // High Speed Ports (without USBR)
+ //
+ Device(HS01)
+ {
+ Name(_ADR, 0x01)
+ }
+
+ Device(HS02)
+ {
+ Name(_ADR, 0x02)
+ }
+
+ Device(HS03)
+ {
+ Name(_ADR, 0x03)
+ }
+
+ Device(HS04)
+ {
+ Name(_ADR, 0x04)
+ }
+
+ Device(HS05)
+ {
+ Name(_ADR, 0x05)
+ }
+
+ Device(HS06)
+ {
+ Name(_ADR, 0x06)
+ }
+
+ Device(HS07)
+ {
+ Name(_ADR, 0x07)
+ }
+
+ Device(HS08)
+ {
+ Name(_ADR, 0x08)
+ }
+
+ Device(HS09)
+ {
+ Name(_ADR, 0x09)
+ }
+
+ Device(HS10)
+ {
+ Name(_ADR, 0x0A)
+ }
+
+ //
+ // USBR port will be known as USBR instead of HS09 / HS15
+ //
+ Device(USR1)
+ {
+ Method(_ADR) { Return (Add(USRA(),0)) }
+ }
+
+ //
+ // USBR port 2 will be known as USBR instead of xxxx
+ //
+ Device(USR2)
+ {
+ Method(_ADR) { Return (Add(USRA(),1)) }
+ }
+
+ //
+ // Super Speed Ports
+ //
+ Device(SS01)
+ {
+ Method(_ADR) { Return (Add(SSPA(),0)) }
+ }
+
+ Device(SS02)
+ {
+ Method(_ADR) { Return (Add(SSPA(),1)) }
+ }
+
+ Device(SS03)
+ {
+ Method(_ADR) { Return (Add(SSPA(),2)) }
+ }
+
+ Device(SS04)
+ {
+ Method(_ADR) { Return (Add(SSPA(),3)) }
+ }
+
+ Device(SS05)
+ {
+ Method(_ADR) { Return (Add(SSPA(),4)) }
+ }
+
+ Device(SS06)
+ {
+ Method(_ADR) { Return (Add(SSPA(),5)) }
+ }
+
+ } // device rhub
+ } // device xhc
+} //scope
+
+//
+// SPT-H
+//
+If(LEqual(PCHV(),SPTH)) {
+ Scope(\_SB_.PCI0.XHC.RHUB) {
+
+ Device(HS11)
+ {
+ Name(_ADR, 0xB)
+ }
+
+ Device(HS12)
+ {
+ Name(_ADR, 0xC)
+ }
+
+ Device(HS13)
+ {
+ Name(_ADR, 0xD)
+ }
+
+ Device(HS14)
+ {
+ Name(_ADR, 0xE)
+ }
+
+ Device(SS07)
+ {
+ Method(_ADR) { Return (Add(SSPA(),6)) }
+ }
+
+ Device(SS08)
+ {
+ Method(_ADR) { Return (Add(SSPA(),7)) }
+ }
+
+ Device(SS09)
+ {
+ Method(_ADR) { Return (Add(SSPA(),8)) }
+ }
+
+ Device(SS10)
+ {
+ Method(_ADR) { Return (Add(SSPA(),9)) }
+ }
+
+ } //scope
+} // if
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl
new file mode 100644
index 0000000000..a8e4f0b34c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl
@@ -0,0 +1,144 @@
+/**@file
+ Trace Hub debug library for ASL code.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#define TRACE_HUB_MASTER_NUM_ASL 32
+#define TRACE_HUB_CHANNEL_NUM_ASL 22
+
+Scope(\){
+ // Check if Trace Hub is enabled
+ Method (THEN, 0, Serialized) {
+ OperationRegion (THBA, SystemMemory, PCH_TRACE_HUB_SW_BASE_ADDRESS, 0x10)
+ Field (THBA, DWordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ DO00, 32,
+ }
+ Return (LNotEqual(DO00, 0xFFFFFFFF))
+ }
+
+ // Trace Hub debug address
+ // This is internal helper runtine of THDS
+ // Arg0 : Master number
+ // Arg1 : Channel number
+ Method (THDA, 2, Serialized) {
+ // Local0 = PCH_TRACE_HUB_SW_BASE_ADDRESS + 0x40 * (V_PCH_TRACE_HUB_MTB_CHLCNT * (Master - V_PCH_TRACE_HUB_MTB_STHMSTR)) + 0x40 * Channel;
+ Store (PCH_TRACE_HUB_SW_BASE_ADDRESS, Local0)
+ Add (Local0, Multiply (0x40, Multiply (V_PCH_TRACE_HUB_MTB_CHLCNT, Subtract (Arg0, V_PCH_TRACE_HUB_MTB_STHMSTR))), Local0)
+ Add (Local0, Multiply (0x40, Arg1), Local0)
+ Return (Local0)
+ }
+
+ // String to raw data
+ // This is internal helper runtine of THDS
+ // Arg0 : string
+ // Arg1 : Index
+ // Arg2 : size
+ Method (STRD, 3, Serialized) {
+ If (LGreater (Add (Arg1, Arg2), SizeOf (Arg0))) {
+ Return (0)
+ }
+ // Local0 is return value
+ // Lccal1 is loop index
+ // Local2 is char of string
+ // Local3 is buffer of string
+ ToBuffer (Arg0, Local3)
+ Store (0, Local0)
+ Store (0, Local1)
+ While (LLess (Local1, Arg2)) {
+ Store (DeRefOf (Index (Local3, Add (Arg1, Local1))), Local2)
+ Add (Local0, ShiftLeft (Local2, Multiply (8, Local1)), Local0)
+ Increment (Local1)
+ }
+ Return (Local0)
+ }
+
+ // Trace Hub debug string
+ // Arg0 : debug string
+ Method (THDS, 1, Serialized) {
+ // TH check if enabled.
+ If (LNot (THEN())) {
+ Return
+ }
+ // Adding newline at the end of the string
+ Concatenate (Arg0, "\n", local2)
+
+ // Local0 is the length of string
+ // Local1 is the debug base address
+ // Local2 is the debug string with "\n"
+ Store (Sizeof (local2), Local0)
+ Store (THDA (TRACE_HUB_MASTER_NUM_ASL, TRACE_HUB_CHANNEL_NUM_ASL), Local1)
+ OperationRegion (THBA, SystemMemory, local1, 0x40)
+ Field (THBA, QWordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ QO00, 64,
+ }
+ Field (THBA, DWordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ DO00, 32,
+ Offset (0x10),
+ DO10, 32,
+ offset (0x30),
+ DO30, 32,
+ }
+ Field (THBA, WordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ WO00, 16,
+ }
+ Field (THBA, ByteAcc, NoLock, Preserve) {
+ Offset (0x00),
+ BO00, 8,
+ }
+
+ // time stamp
+ Store (0x01000242, DO10)
+ // length of string
+ Store (Local0, WO00)
+ // string
+ Store (0, Local6)
+ Store (Local0, Local7)
+ while (LGreaterEqual(Local7, 8)) {
+ Store (STRD (local2, Local6, 8), QO00)
+ Add (Local6, 8, Local6)
+ Subtract (Local7, 8, Local7)
+ }
+ If (LGreaterEqual(Local7, 4)) {
+ Store (STRD (local2, Local6, 4), DO00)
+ Add (Local6, 4, Local6)
+ Subtract (Local7, 4, Local7)
+ }
+ If (LGreaterEqual(Local7, 2)) {
+ Store (STRD (local2, Local6, 2), WO00)
+ Add (Local6, 2, Local6)
+ Subtract (Local7, 2, Local7)
+ }
+ If (LGreaterEqual(Local7, 1)) {
+ Store (STRD (local2, Local6, 1), BO00)
+ Add (Local6, 1, Local6)
+ Subtract (Local7, 1, Local7)
+ }
+ // flag
+ Store (0, DO30)
+ }
+
+ // Trace Hub debug Hex string
+ // Arg0 : Integer, buffer
+ Method (THDH, 1, Serialized) {
+ THDS (ToHexString (Arg0))
+ }
+
+ // Trace Hub debug decimal string
+ // Arg0 : Integer, buffer
+ Method (THDD, 1, Serialized) {
+ THDS (ToDecimalString (Arg0))
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl
new file mode 100644
index 0000000000..5036b4b771
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl
@@ -0,0 +1,70 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+//
+// _DSM : Device Specific Method supporting USB Sideband Deferring function
+//
+// Arg0: UUID Unique function identifier
+// Arg1: Integer Revision Level
+// Arg2: Integer Function Index
+// Arg3: Package Parameters
+//
+Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj})
+{
+
+ If (LEqual(Arg0, ToUUID ("A5FC708F-8775-4BA6-BD0C-BA90A1EC72F8")))
+ {
+ //
+ // Switch by function index
+ //
+ Switch (ToInteger(Arg2))
+ {
+ //
+ // Standard query - A bitmask of functions supported
+ // Supports function 0-2
+ //
+ Case (0)
+ {
+ if (LEqual(Arg1, 1)){ // test Arg1 for the revision
+ Return (Buffer () {0x07})
+ } else {
+ Return (Buffer () {0})
+ }
+ }
+ //
+ // USB Sideband Deferring Support
+ // 0: USB Sideband Deferring not supported on this device
+ // 1: USB Sideband Deferring supported
+ //
+ Case (1)
+ {
+ if (LEqual(SDGV,0xFF)){ // check for valid GPE vector
+ Return (0)
+ } else {
+ Return (1)
+ }
+ }
+ //
+ // GPE Vector
+ // Return the bit offset within the GPE block of the GPIO (HOST_ALERT) driven by this device
+ //
+ Case (2)
+ {
+ Return (SDGV)
+ }
+ }
+ }
+
+ Return(Buffer() {0})
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h
new file mode 100644
index 0000000000..187d4cd506
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h
@@ -0,0 +1,72 @@
+/** @file
+ CIO2 policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _CIO2_CONFIG_H_
+#define _CIO2_CONFIG_H_
+
+#define CIO2_CONFIG_REVISION 1
+extern EFI_GUID gCio2ConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_SKYCAM_CIO2_CONFIG block describes SkyCam CIO2 device.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ NOTE: For SKL PCH, while CIO2 is enabled,
+ RC will configure CIO2 controller as ACPI mode when PCH stepping < C0, and configure to PCI mode for C0 onwards.
+ **/
+ UINT32 DeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled</b>
+
+ UINT32 SkyCamPortATermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port A
+ UINT32 SkyCamPortBTermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port B
+ UINT32 SkyCamPortCTermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port C
+ UINT32 SkyCamPortDTermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port D
+ UINT32 RsvdBits : 26;
+
+ //
+ // CIO2 FLS registers configuration.
+ //
+
+ UINT32 PortATrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port A Clk Trim
+ UINT32 PortBTrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port B Clk Trim
+ UINT32 PortCTrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port C Clk Trim
+ UINT32 PortDTrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port D Clk Trim
+ UINT32 PortACtleEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port A Ctle
+ UINT32 PortBCtleEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port B Ctle
+ UINT32 PortCDCtleEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port C/D Ctle
+ UINT32 RsvdBits0 : 25;
+
+ UINT32 PortACtleCapValue : 4; /// Port A Ctle Cap Value. Default is <b>0xE</b>
+ UINT32 PortBCtleCapValue : 4; /// Port B Ctle Cap Value. Default is <b>0xE</b>
+ UINT32 PortCDCtleCapValue : 4; /// Port C/D Ctle Cap Value. Default is <b>0xE</b>
+ UINT32 PortACtleResValue : 5; /// Port A Ctle Res Value. Default is <b>0xD</b>
+ UINT32 PortBCtleResValue : 5; /// Port B Ctle Res Value. Default is <b>0xD</b>
+ UINT32 PortCDCtleResValue : 5; /// Port C/D Ctle Res Value. Default is <b>0xD</b>
+ UINT32 RsvdBits1 : 5;
+
+ UINT32 PortAClkTrimValue : 4; /// Port A Clk Trim Value. Default is <b>0xA</b>
+ UINT32 PortBClkTrimValue : 4; /// Port B Clk Trim Value. Default is <b>0xA</b>
+ UINT32 PortCClkTrimValue : 4; /// Port C Clk Trim Value. Default is <b>0x9</b>
+ UINT32 PortDClkTrimValue : 4; /// Port D Clk Trim Value. Default is <b>0xA</b>
+ UINT32 PortADataTrimValue : 16; /// Port A Data Trim Value. Default is <b>0xBBBB</b>
+ UINT32 PortBDataTrimValue : 16; /// Port B Data Trim Value. Default is <b>0xBBBB</b>
+ UINT32 PortCDDataTrimValue : 16; /// Port C/D Data Trim Value. Default is <b>0xCCCC</b>
+
+} PCH_CIO2_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CIO2_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h
new file mode 100644
index 0000000000..aba0677abc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h
@@ -0,0 +1,53 @@
+/** @file
+ Dci policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _DCI_CONFIG_H_
+#define _DCI_CONFIG_H_
+
+#define DCI_PREMEM_CONFIG_REVISION 2
+extern EFI_GUID gDciPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to Direct Connection Interface (DCI).
+
+ <b>Revision 1:</b>
+ - Inital version.
+ <b>Revision 2:</b>
+ - Deprecate DciAutoDetect
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ DCI enable (HDCIEN bit)
+ when Enabled, allow DCI to be enabled. When Disabled, the host control is not enabling DCI feature.
+ BIOS provides policy to enable or disable DCI, and user would be able to use BIOS option to change this policy.
+ The user changing the setting from disable to enable, is taken as a consent from the user to enable this DCI feature.
+ <b>0:Disabled</b>; 1:Enabled
+ **/
+ UINT32 DciEn : 1;
+ /**
+ @deprecated from revision 2.
+ <b>(Test)</b> When set to Auto detect mode, it detects CCA being connected during BIOS post time.
+ This policy only applies when DciEn is disabled.
+ NOTE: this policy should not be visible to end customer.
+ 0: Disable AUTO mode, <b>1: Enable AUTO mode</b>
+ **/
+ UINT32 DciAutoDetect : 1;
+ UINT32 RsvdBits : 30; ///< Reserved bits
+} PCH_DCI_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _DCI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h
new file mode 100644
index 0000000000..2fd5d1b171
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h
@@ -0,0 +1,53 @@
+/** @file
+ DMI policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _DMI_CONFIG_H_
+#define _DMI_CONFIG_H_
+
+#define DMI_CONFIG_REVISION 2
+extern EFI_GUID gDmiConfigGuid;
+
+
+#pragma pack (push,1)
+
+
+/**
+ The PCH_DMI_CONFIG block describes the expected configuration of the PCH for DMI.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add LegacyIoLowLatency support.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ 0: Disable; <b>1: Enable</b> ASPM on PCH side of the DMI Link.
+ While DmiAspm is enabled, DMI ASPM will be set to Intel recommended value.
+ **/
+ UINT32 DmiAspm : 1;
+ UINT32 PwrOptEnable : 1; ///< <b>0: Disable</b>; 1: Enable DMI Power Optimizer on PCH side.
+ /**
+ Set to enable low latenc of legacy IO.
+ Some systems require lower IO latency irrespective of power.
+ This is a tradeoff between power and IO latency.
+ @note: Once this is enabled, DmiAspm is forced to disabled and so do Pcie DmiAspm in SystemAgent.
+ <b>0:Disable</b>, 1:Enable
+ **/
+ UINT32 LegacyIoLowLatency : 1;
+ UINT32 Rsvdbits : 29; ///< Reserved bits
+} PCH_DMI_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _DMI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h
new file mode 100644
index 0000000000..c952bf9f31
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h
@@ -0,0 +1,41 @@
+/** @file
+ Espi policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _ESPI_CONFIG_H_
+#define _ESPI_CONFIG_H_
+
+#define ESPI_CONFIG_REVISION 1
+extern EFI_GUID gEspiConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to ESPI.
+
+ <b>Revision 1</b>:
+ - Initial version. Add BmeMasterSlaveEnabled support.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ eSPI Master and Slave BME settings.
+ When TRUE, then the BME bit enabled in eSPI Master and Slave.
+ 0: FALSE, <b>1: TRUE </b>
+ **/
+ UINT32 BmeMasterSlaveEnabled : 1;
+ UINT32 RsvdBits : 31; ///< Reserved bits
+} PCH_ESPI_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _ESPI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h
new file mode 100644
index 0000000000..b55aaa705a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h
@@ -0,0 +1,54 @@
+/** @file
+ FlashProtection policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _FLASH_PROTECTION_CONFIG_H_
+#define _FLASH_PROTECTION_CONFIG_H_
+
+#define FLASH_PROTECTION_CONFIG_REVISION 1
+extern EFI_GUID gFlashProtectionConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH provides a method for blocking writes and reads to specific ranges
+ in the SPI flash when the Protected Ranges are enabled.
+ PROTECTED_RANGE is used to specify if flash protection are enabled,
+ the write protection enable bit and the read protection enable bit,
+ and to specify the upper limit and lower base for each register
+ Platform code is responsible to get the range base by PchGetSpiRegionAddresses routine,
+ and set the limit and base accordingly.
+**/
+typedef struct {
+ UINT32 WriteProtectionEnable : 1; ///< Write or erase is blocked by hardware. <b>0: Disable</b>; 1: Enable.
+ UINT32 ReadProtectionEnable : 1; ///< Read is blocked by hardware. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 30; ///< Reserved
+ /**
+ The address of the upper limit of protection
+ This is a left shifted address by 12 bits with address bits 11:0 are assumed to be FFFh for limit comparison
+ **/
+ UINT16 ProtectedRangeLimit;
+ /**
+ The address of the upper limit of protection
+ This is a left shifted address by 12 bits with address bits 11:0 are assumed to be 0
+ **/
+ UINT16 ProtectedRangeBase;
+} PROTECTED_RANGE;
+
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ PROTECTED_RANGE ProtectRange[PCH_FLASH_PROTECTED_RANGES];
+} PCH_FLASH_PROTECTION_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _FLASH_PROTECTION_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h
new file mode 100644
index 0000000000..a0ebbbd84d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h
@@ -0,0 +1,180 @@
+/** @file
+ HDAUDIO policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _HDAUDIO_CONFIG_H_
+#define _HDAUDIO_CONFIG_H_
+
+#define HDAUDIO_CONFIG_REVISION 2
+extern EFI_GUID gHdAudioConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_HDAUDIO_CONFIG block describes the expected configuration of the Intel HD Audio feature.
+///
+#define PCH_HDAUDIO_AUTO 2
+
+#define HDAUDIO_VERB_TABLE_VIDDID(Vid,Did) (UINT32)((UINT16)Vid | ((UINT16)Did << 16))
+#define HDAUDIO_VERB_TABLE_RID_SDI_SIZE(Rid,Sdi,VerbTableSize) (UINT32)((UINT8)Rid | ((UINT8)Sdi << 8) | ((UINT16)VerbTableSize << 16))
+#define HDAUDIO_VERB_TABLE_CMD_SIZE(VerbTable) ((sizeof (VerbTable) - sizeof (PCH_HDA_VERB_TABLE_HEADER)) / (sizeof (UINT32)))
+
+///
+/// Use this macro to create HDAUDIO_VERB_TABLE and populate size automatically
+///
+#define HDAUDIO_VERB_TABLE_INIT(Vid,Did,Rid,Sdi,...) \
+{ \
+ { Vid, Did, Rid, Sdi, (sizeof((UINT32[]){__VA_ARGS__})/sizeof(UINT32)) }, \
+ { __VA_ARGS__ } \
+}
+
+/**
+ Azalia verb table header
+ Every verb table should contain this defined header and followed by azalia verb commands.
+**/
+typedef struct {
+ UINT16 VendorId; ///< Codec Vendor ID
+ UINT16 DeviceId; ///< Codec Device ID
+ UINT8 RevisionId; ///< Revision ID of the codec. 0xFF matches any revision.
+ UINT8 SdiNum; ///< SDI number, 0xFF matches any SDI.
+ UINT16 DataDwords; ///< Number of data DWORDs following the header.
+} PCH_HDA_VERB_TABLE_HEADER;
+
+#ifdef _MSC_VER
+//
+// Disable "zero-sized array in struct/union" extension warning.
+// Used for neater verb table definitions.
+//
+#pragma warning (push)
+#pragma warning (disable: 4200)
+#endif
+typedef struct {
+ PCH_HDA_VERB_TABLE_HEADER Header;
+ UINT32 Data[];
+} HDAUDIO_VERB_TABLE;
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+enum PCH_HDAUDIO_IO_BUFFER_OWNERSHIP {
+ PchHdaIoBufOwnerHdaLink = 0, ///< HD-Audio link owns all the I/O buffers.
+ PchHdaIoBufOwnerHdaLinkI2sPort = 1, ///< HD-Audio link owns 4 and I2S port owns 4 of the I/O buffers.
+ PchHdaIoBufOwnerI2sPort = 3 ///< I2S0 and I2S1 ports own all the I/O buffers.
+};
+
+enum PCH_HDAUDIO_IO_BUFFER_VOLTAGE {
+ PchHdaIoBuf33V = 0,
+ PchHdaIoBuf18V = 1
+};
+
+enum PCH_HDAUDIO_VC_TYPE {
+ PchHdaVc0 = 0,
+ PchHdaVc1 = 1
+};
+
+enum PCH_HDAUDIO_DMIC_TYPE {
+ PchHdaDmicDisabled = 0,
+ PchHdaDmic2chArray = 1,
+ PchHdaDmic4chArray = 2,
+ PchHdaDmic1chArray = 3
+};
+
+typedef enum {
+ PchHdaLinkFreq6MHz = 0,
+ PchHdaLinkFreq12MHz = 1,
+ PchHdaLinkFreq24MHz = 2,
+ PchHdaLinkFreq48MHz = 3,
+ PchHdaLinkFreq96MHz = 4,
+ PchHdaLinkFreqInvalid
+} PCH_HDAUDIO_LINK_FREQUENCY;
+
+typedef enum {
+ PchHdaIDispMode2T = 0,
+ PchHdaIDispMode1T = 1
+} PCH_HDAUDIO_IDISP_TMODE;
+
+/**
+ This structure contains the policies which are related to HD Audio device (cAVS).
+
+ <b>Revision 1:</b>
+ - Inital version.
+ <b>Revision 2:</b>
+ - Deprecate DspPpModuleMask: Pre/Post-processing modules (3rd Party IP) support moved to Platform Package.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This member describes whether or not Intel HD Audio (Azalia) should be enabled.
+ If enabled (in Auto mode) and no codec exists the reference code will automatically disable
+ the HD Audio device.
+ 0: Disable, 1: Enable, <b>2: Auto (enabled if codec detected and initialized, disabled otherwise)</b>
+ **/
+ UINT32 Enable : 2;
+ UINT32 DspEnable : 1; ///< DSP enablement: 0: Disable; <b>1: Enable</b>
+ UINT32 Pme : 1; ///< Azalia wake-on-ring, <b>0: Disable</b>; 1: Enable
+ UINT32 IoBufferOwnership : 2; ///< I/O Buffer Ownership Select: <b>0: HD-A Link</b>; 1: Shared, HD-A Link and I2S Port; 3: I2S Ports
+ UINT32 IoBufferVoltage : 1; ///< I/O Buffer Voltage Mode Select: <b>0: 3.3V</b>; 1: 1.8V
+ UINT32 VcType : 1; ///< Virtual Channel Type Select: <b>0: VC0</b>, 1: VC1
+ UINT32 HdAudioLinkFrequency : 4; ///< HDA-Link frequency (PCH_HDAUDIO_LINK_FREQUENCY enum): <b>2: 24MHz</b>, 1: 12MHz, 0: 6MHz
+ UINT32 IDispLinkFrequency : 4; ///< iDisp-Link frequency (PCH_HDAUDIO_LINK_FREQUENCY enum): <b>4: 96MHz</b>, 3: 48MHz
+ UINT32 IDispLinkTmode : 1; ///< iDisp-Link T-Mode (PCH_HDAUDIO_IDISP_TMODE enum): <b>0: 2T</b>, 1: 1T
+ /**
+ Universal Audio Architecture compliance for DSP enabled system:
+ <b>0: Not-UAA Compliant (Intel SST driver supported only)</b>,
+ 1: UAA Compliant (HDA Inbox driver or SST driver supported)
+ **/
+ UINT32 DspUaaCompliance : 1;
+ UINT32 IDispCodecDisconnect : 1; ///< iDisplay Audio Codec disconnection, <b>0: Not disconnected, enumerable</b>; 1: Disconnected SDI, not enumerable
+ UINT32 RsvdBits0 : 13; ///< Reserved bits 1
+ /**
+ Bitmask of supported DSP endpoint configuration exposed via NHLT ACPI table:
+ **/
+ UINT32 DspEndpointDmic : 2; ///< DMIC Select (PCH_HDAUDIO_DMIC_TYPE enum): 0: Disable; 1: 2ch array; <b>2: 4ch array</b>; 3: 1ch array
+ UINT32 DspEndpointBluetooth : 1; ///< Bluetooth enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 DspEndpointI2s : 1; ///< I2S enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 RsvdBits1 : 28; ///< Reserved bits 2
+ /**
+ Bitmask of supported DSP features:
+ [BIT0] - WoV; [BIT1] - BT Sideband; [BIT2] - Codec VAD; [BIT5] - BT Intel HFP; [BIT6] - BT Intel A2DP
+ [BIT7] - DSP based speech pre-processing disabled; [BIT8] - 0: Intel WoV, 1: Windows Voice Activation
+ Default is <b>zero</b>.
+ **/
+ UINT32 DspFeatureMask;
+ /**
+ @deprecated from revision 2.
+ Bitmask of supported DSP Pre/Post-Processing Modules.
+ Specific pre/post-processing module bit position must be coherent with the ACPI implementation:
+ \_SB.PCI0.HDAS._DSM Function 3: Query Pre/Post Processing Module Support.
+ DspPpModuleMask is passed to ACPI as 'ADPM' NVS variable
+ Default is <b>zero</b>.
+ **/
+ UINT32 DspPpModuleMask;
+ UINT16 ResetWaitTimer; ///< <b>(Test)</b> The delay timer after Azalia reset, the value is number of microseconds. Default is <b>600</b>.
+ UINT8 Rsvd0; ///< Reserved bytes, align to multiple 4
+ /**
+ Number of the verb table entry defined in VerbTablePtr.
+ Each entry points to a verb table which contains HDAUDIO_VERB_TABLE structure and verb command blocks.
+ **/
+ UINT8 VerbTableEntryNum;
+ /**
+ Pointer to a verb table array.
+ This pointer points to 32bits address, and is only eligible and consumed in post mem phase.
+ Each entry points to a verb table which contains HDAUDIO_VERB_TABLE structure and verb command blocks.
+ The prototype of this is:
+ HDAUDIO_VERB_TABLE **VerbTablePtr;
+ **/
+ UINT32 VerbTablePtr;
+} PCH_HDAUDIO_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HDAUDIO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h
new file mode 100644
index 0000000000..30928e5d08
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h
@@ -0,0 +1,47 @@
+/** @file
+ HPET policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _HPET_CONFIG_H_
+#define _HPET_CONFIG_H_
+
+#define HPET_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHpetPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HPET_CONFIG block passes the bus/device/function value for HPET.
+ The address resource range of HPET must be reserved in E820 and ACPI as
+ system resource.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Determines if enable HPET timer. 0: Disable; <b>1: Enable</b>.
+ The HPET timer address decode is always enabled.
+ This policy is used to configure the HPET timer count, and also the _STA of HPET device in ACPI.
+ While enabled, the HPET timer is started, else the HPET timer is halted.
+ **/
+ UINT32 Enable : 1;
+ UINT32 BdfValid : 1; ///< Whether the BDF value is valid. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits0 : 6; ///< Reserved bits
+ UINT32 BusNumber : 8; ///< Bus Number HPETn used as Requestor / Completer ID. Default is <b>0xF0</b>.
+ UINT32 DeviceNumber : 5; ///< Device Number HPETn used as Requestor / Completer ID. Default is <b>0x1F</b>.
+ UINT32 FunctionNumber : 3; ///< Function Number HPETn used as Requestor / Completer ID. Default is <b>0x00</b>.
+ UINT32 RsvdBits1 : 8; ///< Reserved bits
+ UINT32 Base; ///< The HPET base address. Default is <b>0xFED00000</b>.
+} PCH_HPET_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HPET_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h
new file mode 100644
index 0000000000..e4973fc25e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h
@@ -0,0 +1,45 @@
+/** @file
+ HSIO policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _HSIO_CONFIG_H_
+#define _HSIO_CONFIG_H_
+
+#define HSIO_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_PREMEM_CONFIG block provides HSIO message related settings.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ /**
+ <b>(Test)</b>
+ 0- Disable, disable will prevent the HSIO version check and ChipsetInit HECI message from being sent
+ <b>1- Enable</b> ChipsetInit HECI message
+ **/
+ UINT32 ChipsetInitMessage : 1;
+ /**
+ <b>(Test)</b>
+ <b>0- Disable</b>
+ 1- Enable When eanbled, this is used to bypass the reset after ChipsetInit HECI message.
+ **/
+ UINT32 BypassPhySyncReset : 1;
+ UINT32 RsvdBits : 30;
+} PCH_HSIO_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h
new file mode 100644
index 0000000000..cf7bd6251a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h
@@ -0,0 +1,76 @@
+/** @file
+ HSIO pcie policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _HSIO_PCIE_CONFIG_H_
+#define _HSIO_PCIE_CONFIG_H_
+
+#define HSIO_PCIE_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioPciePreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_PCIE_LANE_CONFIG describes HSIO settings for PCIe lane
+**/
+typedef struct {
+ //
+ // HSIO Rx Eq
+ // Refer to the EDS for recommended values.
+ // Note that these setting are per-lane and not per-port
+ //
+ UINT32 HsioRxSetCtleEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 3 Set CTLE Value
+ UINT32 HsioRxSetCtle : 6; ///< PCH PCIe Gen 3 Set CTLE Value
+ UINT32 HsioTxGen1DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 1 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen1DownscaleAmp : 6; ///< PCH PCIe Gen 1 TX Output Downscale Amplitude Adjustment value
+ UINT32 HsioTxGen2DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen2DownscaleAmp : 6; ///< PCH PCIe Gen 2 TX Output Downscale Amplitude Adjustment value
+ UINT32 HsioTxGen3DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 3 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen3DownscaleAmp : 6; ///< PCH PCIe Gen 3 TX Output Downscale Amplitude Adjustment value
+ UINT32 RsvdBits0 : 4; ///< Reserved Bits
+
+ UINT32 HsioTxGen1DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 1 TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen1DeEmph : 6; ///< PCH PCIe Gen 1 TX Output De-Emphasis Adjustment Setting
+ UINT32 HsioTxGen2DeEmph3p5Enable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output -3.5dB Mode De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph3p5 : 6; ///< PCH PCIe Gen 2 TX Output -3.5dB Mode De-Emphasis Adjustment Setting
+ UINT32 HsioTxGen2DeEmph6p0Enable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output -6.0dB Mode De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph6p0 : 6; ///< PCH PCIe Gen 2 TX Output -6.0dB Mode De-Emphasis Adjustment Setting
+ UINT32 RsvdBits1 : 11; ///< Reserved Bits
+} PCH_HSIO_PCIE_LANE_CONFIG;
+
+/**
+ The PCH_HSIO_PCIE_CONFIG block describes the configuration of the HSIO for PCIe lanes
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add PciePllSsc support.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of HSIO for PCIe lanes.
+ ///
+ PCH_HSIO_PCIE_LANE_CONFIG Lane[PCH_MAX_PCIE_ROOT_PORTS];
+ /**
+ Specifies the Pcie Pll Spread Spectrum Percentage
+ The value of this policy is in 1/10th percent units.
+ Valid spread range is 0-20. A value of 0xFF is reserved for AUTO.
+ A value of 0 is SSC of 0.0%. A value of 20 is SSC of 2.0%
+ The default is <b>0xFF: AUTO - No BIOS override</b>.
+ **/
+ UINT8 PciePllSsc;
+ UINT8 Reserved[3];
+} PCH_HSIO_PCIE_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_PCIE_LANE_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h
new file mode 100644
index 0000000000..53c1a01a17
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h
@@ -0,0 +1,71 @@
+/** @file
+ Hsio Sata policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _HSIO_SATA_CONFIG_H_
+#define _HSIO_SATA_CONFIG_H_
+
+#define HSIO_SATA_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioSataPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_SATA_PORT_LANE describes HSIO settings for SATA Port lane
+**/
+typedef struct {
+ //
+ // HSIO Rx Eq
+ //
+ UINT32 HsioRxGen1EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen1EqBoostMag : 6; ///< SATA 1.5 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ UINT32 HsioRxGen2EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen2EqBoostMag : 6; ///< SATA 3.0 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ UINT32 HsioRxGen3EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen3EqBoostMag : 6; ///< SATA 6.0 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ //
+ // HSIO Tx Eq
+ //
+ UINT32 HsioTxGen1DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 1.5 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen1DownscaleAmp : 6; ///< SATA 1.5 Gb/s TX Output Downscale Amplitude Adjustment value
+ UINT32 RsvdBits0 : 4; ///< Reserved bits
+
+ UINT32 HsioTxGen2DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 3.0 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen2DownscaleAmp : 6; ///< SATA 3.0 Gb/s TX Output Downscale Amplitude Adjustment
+ UINT32 HsioTxGen3DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 6.0 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen3DownscaleAmp : 6; ///< SATA 6.0 Gb/s TX Output Downscale Amplitude Adjustment
+ UINT32 HsioTxGen1DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 1.5 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen1DeEmph : 6; ///< SATA 1.5 Gb/s TX Output De-Emphasis Adjustment Setting
+
+ UINT32 HsioTxGen2DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 3.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph : 6; ///< SATA 3.0 Gb/s TX Output De-Emphasis Adjustment Setting
+ UINT32 RsvdBits1 : 4; ///< Reserved bits
+
+ UINT32 HsioTxGen3DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 6.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen3DeEmph : 6; ///< SATA 6.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 RsvdBits2 : 25; ///< Reserved bits
+} PCH_HSIO_SATA_PORT_LANE;
+
+///
+/// The PCH_HSIO_SATA_CONFIG block describes the HSIO configuration of the SATA controller.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of HSIO for SATA lanes.
+ ///
+ PCH_HSIO_SATA_PORT_LANE PortLane[PCH_MAX_SATA_PORTS];
+} PCH_HSIO_SATA_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_SATA_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h
new file mode 100644
index 0000000000..3b8e247a31
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h
@@ -0,0 +1,63 @@
+/** @file
+ Interrupt policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _INTERRUPT_CONFIG_H_
+#define _INTERRUPT_CONFIG_H_
+
+#define INTERRUPT_CONFIG_REVISION 1
+extern EFI_GUID gInterruptConfigGuid;
+
+#pragma pack (push,1)
+
+//
+// --------------------- Interrupts Config ------------------------------
+//
+typedef enum {
+ PchNoInt, ///< No Interrupt Pin
+ PchIntA,
+ PchIntB,
+ PchIntC,
+ PchIntD
+} PCH_INT_PIN;
+
+///
+/// The PCH_DEVICE_INTERRUPT_CONFIG block describes interrupt pin, IRQ and interrupt mode for PCH device.
+///
+typedef struct {
+ UINT8 Device; ///< Device number
+ UINT8 Function; ///< Device function
+ UINT8 IntX; ///< Interrupt pin: INTA-INTD (see PCH_INT_PIN)
+ UINT8 Irq; ///< IRQ to be set for device.
+} PCH_DEVICE_INTERRUPT_CONFIG;
+
+#define PCH_MAX_DEVICE_INTERRUPT_CONFIG 64 ///< Number of all PCH devices
+#define PCH_MAX_PXRC_CONFIG 8 ///< Number of PXRC registers in ITSS
+
+///
+/// The PCH_INTERRUPT_CONFIG block describes interrupt settings for PCH.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT8 NumOfDevIntConfig; ///< Number of entries in DevIntConfig table
+ UINT8 Rsvd0[3]; ///< Reserved bytes, align to multiple 4.
+ PCH_DEVICE_INTERRUPT_CONFIG DevIntConfig[PCH_MAX_DEVICE_INTERRUPT_CONFIG]; ///< Array which stores PCH devices interrupts settings
+ UINT8 PxRcConfig[PCH_MAX_PXRC_CONFIG]; ///< Array which stores interrupt routing for 8259 controller
+ UINT8 GpioIrqRoute; ///< Interrupt routing for GPIO. Default is <b>14</b>.
+ UINT8 SciIrqSelect; ///< Interrupt select for SCI. Default is <b>9</b>.
+ UINT8 TcoIrqSelect; ///< Interrupt select for TCO. Default is <b>9</b>.
+ UINT8 TcoIrqEnable; ///< Enable IRQ generation for TCO. <b>0: Disable</b>; 1: Enable.
+} PCH_INTERRUPT_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _INTERRUPT_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h
new file mode 100644
index 0000000000..c96e3a3a04
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h
@@ -0,0 +1,61 @@
+/** @file
+ IoApic policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _IOAPIC_CONFIG_H_
+#define _IOAPIC_CONFIG_H_
+
+#define IOAPIC_CONFIG_REVISION 1
+extern EFI_GUID gIoApicConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_IOAPIC_CONFIG block describes the expected configuration of the PCH
+ IO APIC, it's optional and PCH code would ignore it if the BdfValid bit is
+ not TRUE. Bus:device:function fields will be programmed to the register
+ P2SB IBDF(P2SB PCI offset R6Ch-6Dh), it's using for the following purpose:
+ As the Requester ID when initiating Interrupt Messages to the processor.
+ As the Completer ID when responding to the reads targeting the IOxAPI's
+ Memory-Mapped I/O registers.
+ This field defaults to Bus 0: Device 31: Function 0 after reset. BIOS can
+ program this field to provide a unique Bus:Device:Function number for the
+ internal IOxAPIC.
+ The address resource range of IOAPIC must be reserved in E820 and ACPI as
+ system resource.
+**/
+typedef struct {
+ /**
+ Revision 1: Init version
+ **/
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 BdfValid : 1; ///< Set to 1 if BDF value is valid, PCH code will not program these fields if this bit is not TRUE. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits0 : 7; ///< Reserved bits
+ UINT32 BusNumber : 8; ///< Bus/Device/Function used as Requestor / Completer ID. Default is <b>0xF0</b>.
+ UINT32 DeviceNumber : 5; ///< Bus/Device/Function used as Requestor / Completer ID. Default is <b>0x1F</b>.
+ UINT32 FunctionNumber : 3; ///< Bus/Device/Function used as Requestor / Completer ID. Default is <b>0x00</b>.
+ UINT32 IoApicEntry24_119 : 1; ///< 0: Disable; <b>1: Enable</b> IOAPIC Entry 24-119
+ /**
+ Enable 8254 Static Clock Gating during early POST time. <b>0: Disable</b>, 1: Enable
+ Set 8254CGE=1 in POST time might fail to boot legacy OS which using 8254 timer.
+ Make sure it won't break legacy OS boot before enabling this.
+ **/
+ UINT32 Early8254ClockGatingEnable : 1;
+ UINT32 RsvdBits1 : 6; ///< Reserved bits
+ UINT8 IoApicId; ///< This member determines IOAPIC ID. Default is <b>0x02</b>.
+ UINT8 ApicRangeSelect; ///< Define address bits 19:12 for the IOxAPIC range. Default is <b>0</b>
+ UINT8 Rsvd0[2]; ///< Reserved bytes
+} PCH_IOAPIC_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _IOAPIC_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h
new file mode 100644
index 0000000000..6a4f6c9ee0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h
@@ -0,0 +1,48 @@
+/** @file
+ ISH policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _ISH_CONFIG_H_
+#define _ISH_CONFIG_H_
+
+#define ISH_CONFIG_REVISION 1
+extern EFI_GUID gIshConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_ISH_CONFIG block describes Integrated Sensor Hub device.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 Enable : 1; ///< ISH Controler 0: Disable; <b>1: Enable</b>.
+ UINT32 SpiGpioAssign : 1; ///< ISH SPI GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 Uart0GpioAssign : 1; ///< ISH UART0 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 Uart1GpioAssign : 1; ///< ISH UART1 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 I2c0GpioAssign : 1; ///< ISH I2C0 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 I2c1GpioAssign : 1; ///< ISH I2C1 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 I2c2GpioAssign : 1; ///< ISH I2C2 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 Gp0GpioAssign : 1; ///< ISH GP_0 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp1GpioAssign : 1; ///< ISH GP_1 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp2GpioAssign : 1; ///< ISH GP_2 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp3GpioAssign : 1; ///< ISH GP_3 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp4GpioAssign : 1; ///< ISH GP_4 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp5GpioAssign : 1; ///< ISH GP_5 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp6GpioAssign : 1; ///< ISH GP_6 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp7GpioAssign : 1; ///< ISH GP_7 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 PdtUnlock : 1; ///< ISH PDT Unlock Msg: <b>0: False</b> 1: True
+ UINT32 RsvdBits0 : 16; ///< Reserved Bits
+} PCH_ISH_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _ISH_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h
new file mode 100644
index 0000000000..980f3ac709
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h
@@ -0,0 +1,44 @@
+/** @file
+ Lan policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _LAN_CONFIG_H_
+#define _LAN_CONFIG_H_
+
+#define LAN_CONFIG_REVISION 1
+extern EFI_GUID gLanConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ PCH intergrated LAN controller configuration settings.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Determines if enable PCH internal LAN, 0: Disable; <b>1: Enable</b>.
+ When Enable is changed (from disabled to enabled or from enabled to disabled),
+ it needs to set LAN Disable regsiter, which might be locked by FDSWL register.
+ So it's recommendated to issue a global reset when changing the status for PCH Internal LAN.
+ **/
+ UINT32 Enable : 1;
+ UINT32 LtrEnable : 1; ///< <b>0: Disable</b>; 1: Enable LTR capabilty of PCH internal LAN.
+ UINT32 K1OffEnable : 1; ///< Use CLKREQ for GbE power management; 1: Enabled, <b>0: Disabled</b>;
+ UINT32 RsvdBits0 : 4; ///< Reserved bits
+ UINT32 ClkReqSupported : 1; ///< Indicate whether dedicated CLKREQ# is supported; 1: Enabled, <b>0: Disabled</b>;
+ UINT32 ClkReqNumber : 4; ///< CLKREQ# used by GbE. Valid if ClkReqSupported is TRUE.
+ UINT32 RsvdBits1 : 20; ///< Reserved bits
+} PCH_LAN_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LAN_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h
new file mode 100644
index 0000000000..f083b3b50c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h
@@ -0,0 +1,67 @@
+/** @file
+ Lock down policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _LOCK_DOWN_CONFIG_H_
+#define _LOCK_DOWN_CONFIG_H_
+
+#define LOCK_DOWN_CONFIG_REVISION 1
+extern EFI_GUID gLockDownConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_LOCK_DOWN_CONFIG block describes the expected configuration of the PCH
+ for security requirement.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ <b>(Test)</b> Enable SMI_LOCK bit to prevent writes to the Global SMI Enable bit. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 GlobalSmi : 1;
+ /**
+ <b>(Test)</b> Enable BIOS Interface Lock Down bit to prevent writes to the Backup Control Register
+ Top Swap bit and the General Control and Status Registers Boot BIOS Straps. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosInterface : 1;
+ /**
+ <b>(Test)</b> Enable RTC lower and upper 128 byte Lock bits to lock Bytes 38h-3Fh in the upper
+ and lower 128-byte bank of RTC RAM. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 RtcLock : 1;
+ /**
+ Enable the BIOS Lock Enable (BLE) feature and set EISS bit (D31:F5:RegDCh[5])
+ for the BIOS region protection. When it is enabled, the BIOS Region can only be
+ modified from SMM after EndOfDxe protocol is installed.
+ Note: When BiosLock is enabled, platform code also needs to update to take care
+ of BIOS modification (including SetVariable) in DXE or runtime phase after
+ EndOfDxe protocol is installed. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosLock : 1;
+ /**
+ Enable InSMM.STS (EISS) in SPI
+ If this bit is set, then WPD must be a '1' and InSMM.STS must be '1' also
+ in order to write to BIOS regions of SPI Flash. If this bit is clear,
+ then the InSMM.STS is a don't care.
+ The BIOS must set the EISS bit while BIOS Guard support is enabled.
+ In recovery path, platform can temporary disable EISS for SPI programming in
+ PEI phase or early DXE phase.
+ 0: Clear EISS bit; <b>1: Set EISS bit</b>.
+ **/
+ UINT32 SpiEiss : 1;
+ UINT32 RsvdBits0 : 27; ///< Reserved bits
+} PCH_LOCK_DOWN_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LOCK_DOWN_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h
new file mode 100644
index 0000000000..be1613a5c2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h
@@ -0,0 +1,39 @@
+/** @file
+ Lpc policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _LPC_CONFIG_H_
+#define _LPC_CONFIG_H_
+
+#define LPC_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gLpcPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to LPC.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Enhance the port 8xh decoding.
+ Original LPC only decodes one byte of port 80h, with this enhancement LPC can decode word or dword of port 80h-83h.
+ @note: this will occupy one LPC generic IO range register. While this is enabled, read from port 80h always return 0x00.
+ 0: Disable, <b>1: Enable</b>
+ **/
+ UINT32 EnhancePort8xhDecoding : 1;
+ UINT32 RsvdBits : 31; ///< Reserved bits
+} PCH_LPC_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LPC_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h
new file mode 100644
index 0000000000..60b9828ebf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h
@@ -0,0 +1,50 @@
+/** @file
+ P2sb policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _P2SB_CONFIG_H_
+#define _P2SB_CONFIG_H_
+
+#define P2SB_CONFIG_REVISION 2
+extern EFI_GUID gP2sbConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to P2SB device.
+ <b>Revision 1:</b>
+ - Init version
+ <b>Revision 2:</b>
+ - Deprecate PsfUnlock and Add SbAccessUnlock to not lock SideBand register access.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ <b>(Test)</b>
+ This unlock the SBI lock bit to allow SBI after post time. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbiUnlock" unless necessary.
+ **/
+ UINT32 SbiUnlock : 1;
+ UINT32 PsfUnlock : 1; //@deprecated
+ /**
+ <b>(Test)</b>
+ The SideBand registers will be locked before 3rd party code execution.
+ This policy unlock the SideBand space. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbAccessUnlock" unless necessary.
+ **/
+ UINT32 SbAccessUnlock : 1;
+ UINT32 RsvdBits : 29;
+} PCH_P2SB_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _P2SB_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
new file mode 100644
index 0000000000..c946e9a116
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
@@ -0,0 +1,60 @@
+/** @file
+ PCH General policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_GENERAL_CONFIG_H_
+#define _PCH_GENERAL_CONFIG_H_
+
+#define PCH_GENERAL_CONFIG_REVISION 1
+#define PCH_GENERAL_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gPchGeneralConfigGuid;
+extern EFI_GUID gPchGeneralPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+enum PCH_RESERVED_PAGE_ROUTE {
+ PchReservedPageToLpc, ///< Port 80h cycles are sent to LPC.
+ PchReservedPageToPcie ///< Port 80h cycles are sent to PCIe.
+};
+
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Subsystem Vendor ID and Subsystem ID of the PCH devices.
+ This fields will be ignored if the value of SubSystemVendorId and SubSystemId
+ are both 0.
+ **/
+ UINT16 SubSystemVendorId; ///< Default Subsystem Vendor ID of the PCH devices. Default is <b>0x8086</b>
+ UINT16 SubSystemId; ///< Default Subsystem ID of the PCH devices. Default is <b>0x7270</b>
+ /**
+ This member describes whether or not the Compatibility Revision ID (CRID) feature
+ of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Crid : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_GENERAL_CONFIG;
+
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT16 AcpiBase; ///< Power management I/O base address. Default is <b>0x1800</b>.
+ UINT8 RsvdBytes[2];
+ /**
+ Control where the Port 80h cycles are sent, <b>0: LPC</b>; 1: PCI.
+ **/
+ UINT32 Port80Route : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_GENERAL_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PCH_GENERAL_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h
new file mode 100644
index 0000000000..873386afe7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h
@@ -0,0 +1,435 @@
+/** @file
+ Pcie root port policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PCIE_CONFIG_H_
+#define _PCH_PCIE_CONFIG_H_
+
+#define PCIE_RP_CONFIG_REVISION 4
+#define PCIE_RP_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gPcieRpConfigGuid;
+extern EFI_GUID gPcieRpPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+#define PCH_PCIE_SWEQ_COEFFS_MAX 5
+
+typedef enum {
+ PchPcieOverrideDisabled = 0,
+ PchPcieL1L2Override = 0x01,
+ PchPcieL1SubstatesOverride = 0x02,
+ PchPcieL1L2AndL1SubstatesOverride = 0x03,
+ PchPcieLtrOverride = 0x04
+} PCH_PCIE_OVERRIDE_CONFIG;
+
+/**
+ PCIe device table entry entry
+
+ The PCIe device table is being used to override PCIe device ASPM settings.
+ To take effect table consisting of such entries must be instelled as PPI
+ on gPchPcieDeviceTablePpiGuid.
+ Last entry VendorId must be 0.
+**/
+typedef struct {
+ UINT16 VendorId; ///< The vendor Id of Pci Express card ASPM setting override, 0xFFFF means any Vendor ID
+ UINT16 DeviceId; ///< The Device Id of Pci Express card ASPM setting override, 0xFFFF means any Device ID
+ UINT8 RevId; ///< The Rev Id of Pci Express card ASPM setting override, 0xFF means all steppings
+ UINT8 BaseClassCode; ///< The Base Class Code of Pci Express card ASPM setting override, 0xFF means all base class
+ UINT8 SubClassCode; ///< The Sub Class Code of Pci Express card ASPM setting override, 0xFF means all sub class
+ UINT8 EndPointAspm; ///< Override device ASPM (see: PCH_PCIE_ASPM_CONTROL)
+ ///< Bit 1 must be set in OverrideConfig for this field to take effect
+ UINT16 OverrideConfig; ///< The override config bitmap (see: PCH_PCIE_OVERRIDE_CONFIG).
+ /**
+ The L1Substates Capability Offset Override. (applicable if bit 2 is set in OverrideConfig)
+ This field can be zero if only the L1 Substate value is going to be override.
+ **/
+ UINT16 L1SubstatesCapOffset;
+ /**
+ L1 Substate Capability Mask. (applicable if bit 2 is set in OverrideConfig)
+ Set to zero then the L1 Substate Capability [3:0] is ignored, and only L1s values are override.
+ Only bit [3:0] are applicable. Other bits are ignored.
+ **/
+ UINT8 L1SubstatesCapMask;
+ /**
+ L1 Substate Port Common Mode Restore Time Override. (applicable if bit 2 is set in OverrideConfig)
+ L1sCommonModeRestoreTime and L1sTpowerOnScale can have a valid value of 0, but not the L1sTpowerOnValue.
+ If L1sTpowerOnValue is zero, all L1sCommonModeRestoreTime, L1sTpowerOnScale, and L1sTpowerOnValue are ignored,
+ and only L1SubstatesCapOffset is override.
+ **/
+ UINT8 L1sCommonModeRestoreTime;
+ /**
+ L1 Substate Port Tpower_on Scale Override. (applicable if bit 2 is set in OverrideConfig)
+ L1sCommonModeRestoreTime and L1sTpowerOnScale can have a valid value of 0, but not the L1sTpowerOnValue.
+ If L1sTpowerOnValue is zero, all L1sCommonModeRestoreTime, L1sTpowerOnScale, and L1sTpowerOnValue are ignored,
+ and only L1SubstatesCapOffset is override.
+ **/
+ UINT8 L1sTpowerOnScale;
+ /**
+ L1 Substate Port Tpower_on Value Override. (applicable if bit 2 is set in OverrideConfig)
+ L1sCommonModeRestoreTime and L1sTpowerOnScale can have a valid value of 0, but not the L1sTpowerOnValue.
+ If L1sTpowerOnValue is zero, all L1sCommonModeRestoreTime, L1sTpowerOnScale, and L1sTpowerOnValue are ignored,
+ and only L1SubstatesCapOffset is override.
+ **/
+ UINT8 L1sTpowerOnValue;
+
+ /**
+ SnoopLatency bit definition
+ Note: All Reserved bits must be set to 0
+
+ BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid
+ When clear values in bits 9:0 will be ignored
+ BITS[14:13] - Reserved
+ BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits
+ 000b - 1 ns
+ 001b - 32 ns
+ 010b - 1024 ns
+ 011b - 32,768 ns
+ 100b - 1,048,576 ns
+ 101b - 33,554,432 ns
+ 110b - Reserved
+ 111b - Reserved
+ BITS[9:0] - Snoop Latency Value. The value in these bits will be multiplied with
+ the scale in bits 12:10
+
+ This field takes effect only if bit 3 is set in OverrideConfig.
+ **/
+ UINT16 SnoopLatency;
+ /**
+ NonSnoopLatency bit definition
+ Note: All Reserved bits must be set to 0
+
+ BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid
+ When clear values in bits 9:0 will be ignored
+ BITS[14:13] - Reserved
+ BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits
+ 000b - 1 ns
+ 001b - 32 ns
+ 010b - 1024 ns
+ 011b - 32,768 ns
+ 100b - 1,048,576 ns
+ 101b - 33,554,432 ns
+ 110b - Reserved
+ 111b - Reserved
+ BITS[9:0] - Non Snoop Latency Value. The value in these bits will be multiplied with
+ the scale in bits 12:10
+
+ This field takes effect only if bit 3 is set in OverrideConfig.
+ **/
+ UINT16 NonSnoopLatency;
+
+ /**
+ Forces LTR override to be permanent
+ The default way LTR override works is:
+ rootport uses LTR override values provided by BIOS until connected device sends an LTR message, then it will use values from the message
+ This settings allows force override of LTR mechanism. If it's enabled, then:
+ rootport will use LTR override values provided by BIOS forever; LTR messages sent from connected device will be ignored
+ **/
+ UINT8 ForceLtrOverride;
+ UINT8 Reserved[3];
+} PCH_PCIE_DEVICE_OVERRIDE;
+
+enum PCH_PCIE_SPEED {
+ PchPcieAuto,
+ PchPcieGen1,
+ PchPcieGen2,
+ PchPcieGen3
+};
+
+///
+/// The values before AutoConfig match the setting of PCI Express Base Specification 1.1, please be careful for adding new feature
+///
+typedef enum {
+ PchPcieAspmDisabled,
+ PchPcieAspmL0s,
+ PchPcieAspmL1,
+ PchPcieAspmL0sL1,
+ PchPcieAspmAutoConfig,
+ PchPcieAspmMax
+} PCH_PCIE_ASPM_CONTROL;
+
+/**
+ Refer to PCH EDS for the PCH implementation values corresponding
+ to below PCI-E spec defined ranges
+**/
+typedef enum {
+ PchPcieL1SubstatesDisabled,
+ PchPcieL1SubstatesL1_1,
+ PchPcieL1SubstatesL1_2,
+ PchPcieL1SubstatesL1_1_2,
+ PchPcieL1SubstatesMax
+} PCH_PCIE_L1SUBSTATES_CONTROL;
+
+enum PCH_PCIE_MAX_PAYLOAD {
+ PchPcieMaxPayload128 = 0,
+ PchPcieMaxPayload256,
+ PchPcieMaxPayloadMax
+};
+
+enum PCH_PCIE_COMPLETION_TIMEOUT {
+ PchPcieCompletionTO_Default,
+ PchPcieCompletionTO_50_100us,
+ PchPcieCompletionTO_1_10ms,
+ PchPcieCompletionTO_16_55ms,
+ PchPcieCompletionTO_65_210ms,
+ PchPcieCompletionTO_260_900ms,
+ PchPcieCompletionTO_1_3P5s,
+ PchPcieCompletionTO_4_13s,
+ PchPcieCompletionTO_17_64s,
+ PchPcieCompletionTO_Disabled
+};
+
+typedef enum {
+ PchPcieEqDefault = 0, ///< Use reference code default (software margining)
+ PchPcieEqHardware = 1, ///< Hardware equalization (experimental), note this requires PCH-LP C0 or PCH-H D0 or newer
+ PchPcieEqSoftware = 2, ///< Use software margining flow
+ PchPcieEqStaticCoeff = 4 ///< Fixed equalization (requires Coefficient settings per lane)
+} PCH_PCIE_EQ_METHOD;
+
+/**
+ Represent lane specific PCIe Gen3 equalization parameters.
+**/
+typedef struct {
+ UINT8 Cm; ///< Coefficient C-1
+ UINT8 Cp; ///< Coefficient C+1
+ UINT8 Rsvd0[2]; ///< Reserved bytes
+} PCH_PCIE_EQ_LANE_PARAM, PCH_PCIE_EQ_PARAM;
+
+/**
+ The PCH_PCI_EXPRESS_ROOT_PORT_CONFIG describe the feature and capability of each PCH PCIe root port.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< @deprecated.
+ UINT32 HotPlug : 1; ///< Indicate whether the root port is hot plug available. <b>0: Disable</b>; 1: Enable.
+ UINT32 PmSci : 1; ///< Indicate whether the root port power manager SCI is enabled. 0: Disable; <b>1: Enable</b>.
+ UINT32 ExtSync : 1; ///< Indicate whether the extended synch is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 TransmitterHalfSwing : 1; ///< Indicate whether the Transmitter Half Swing is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 AcsEnabled : 1; ///< Indicate whether the ACS is enabled. 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 5; ///< Reserved bits.
+ UINT32 ClkReqSupported : 1; ///< Indicate whether dedicated CLKREQ# is supported by the port.
+ /**
+ The ClkReq Signal mapped to this root port. Default is zero. Valid if ClkReqSupported is TRUE.
+ This Number should not exceed the Maximum Available ClkReq Signals for LP and H.
+ **/
+ UINT32 ClkReqNumber : 4;
+ /**
+ Probe CLKREQ# signal before enabling CLKREQ# based power management.
+ Conforming device shall hold CLKREQ# low until CPM is enabled. This feature attempts
+ to verify CLKREQ# signal is connected by testing pad state before enabling CPM.
+ In particular this helps to avoid issues with open-ended PCIe slots.
+ This is only applicable to non hot-plug ports.
+ <b>0: Disable</b>; 1: Enable.
+ **/
+ UINT32 ClkReqDetect : 1;
+ //
+ // Error handlings
+ //
+ UINT32 AdvancedErrorReporting : 1; ///< Indicate whether the Advanced Error Reporting is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 UnsupportedRequestReport : 1; ///< Indicate whether the Unsupported Request Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 FatalErrorReport : 1; ///< Indicate whether the Fatal Error Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 NoFatalErrorReport : 1; ///< Indicate whether the No Fatal Error Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 CorrectableErrorReport : 1; ///< Indicate whether the Correctable Error Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 SystemErrorOnFatalError : 1; ///< Indicate whether the System Error on Fatal Error is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 SystemErrorOnNonFatalError : 1; ///< Indicate whether the System Error on Non Fatal Error is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 SystemErrorOnCorrectableError : 1; ///< Indicate whether the System Error on Correctable Error is enabled. <b>0: Disable</b>; 1: Enable.
+ /**
+ Max Payload Size supported, Default <b>128B</b>, see enum PCH_PCIE_MAX_PAYLOAD
+ Changes Max Payload Size Supported field in Device Capabilities of the root port.
+ **/
+ UINT32 MaxPayload : 2;
+ UINT32 EnableHotplugSmi : 1; ///< Indicate whether the Hotplug Smi for Rootport is enabled, for TBT rootport we need to disable hotplug smi. 0: Disable; <b>1: Enable </b>.
+ UINT32 RsvdBits1 : 3; ///< Reserved fields for future expansion w/o protocol change
+
+ UINT32 DeviceResetPadActiveHigh : 1; ///< Indicated whether PERST# is active <b>0: Low</b>; 1: High, See: DeviceResetPad
+ /**
+ Determines each PCIE Port speed capability.
+ <b>0: Auto</b>; 1: Gen1; 2: Gen2; 3: Gen3 (see: PCH_PCIE_SPEED)
+ **/
+ UINT8 PcieSpeed;
+ /**
+ PCIe Gen3 Equalization Phase 3 Method (see PCH_PCIE_EQ_METHOD).
+ <b>0: Default</b>; 2: Software Search; 4: Fixed Coefficients
+ **/
+ UINT8 Gen3EqPh3Method;
+
+ UINT8 PhysicalSlotNumber; ///< Indicates the slot number for the root port. Default is the value as root port index.
+ UINT8 CompletionTimeout; ///< The completion timeout configuration of the root port (see: PCH_PCIE_COMPLETION_TIMEOUT). Default is <b>PchPcieCompletionTO_Default</b>.
+ /**
+ The PCH pin assigned to device PERST# signal if available, zero otherwise.
+ This entry is used mainly in Gen3 software equalization flow. It is necessary for some devices
+ (mainly some graphic adapters) to successfully complete the software equalization flow.
+ See also DeviceResetPadActiveHigh
+ **/
+ UINT32 DeviceResetPad;
+ UINT32 Rsvd1; ///< Reserved bytes
+ //
+ // Power Management
+ //
+ UINT8 Aspm; ///< The ASPM configuration of the root port (see: PCH_PCIE_ASPM_CONTROL). Default is <b>PchPcieAspmAutoConfig</b>.
+ UINT8 L1Substates; ///< The L1 Substates configuration of the root port (see: PCH_PCIE_L1SUBSTATES_CONTROL). Default is <b>PchPcieL1SubstatesL1_1_2</b>.
+ UINT8 LtrEnable; ///< Latency Tolerance Reporting Mechanism. <b>0: Disable</b>; 1: Enable.
+ UINT8 LtrConfigLock; ///< <b>0: Disable</b>; 1: Enable.
+ UINT16 LtrMaxSnoopLatency; ///< <b>(Test)</b> Latency Tolerance Reporting, Max Snoop Latency.
+ UINT16 LtrMaxNoSnoopLatency; ///< <b>(Test)</b> Latency Tolerance Reporting, Max Non-Snoop Latency.
+ UINT8 SnoopLatencyOverrideMode; ///< <b>(Test)</b> Latency Tolerance Reporting, Snoop Latency Override Mode.
+ UINT8 SnoopLatencyOverrideMultiplier; ///< <b>(Test)</b> Latency Tolerance Reporting, Snoop Latency Override Multiplier.
+ UINT16 SnoopLatencyOverrideValue; ///< <b>(Test)</b> Latency Tolerance Reporting, Snoop Latency Override Value.
+ UINT8 NonSnoopLatencyOverrideMode; ///< <b>(Test)</b> Latency Tolerance Reporting, Non-Snoop Latency Override Mode.
+ UINT8 NonSnoopLatencyOverrideMultiplier; ///< <b>(Test)</b> Latency Tolerance Reporting, Non-Snoop Latency Override Multiplier.
+ UINT16 NonSnoopLatencyOverrideValue; ///< <b>(Test)</b> Latency Tolerance Reporting, Non-Snoop Latency Override Value.
+ UINT32 SlotPowerLimitScale : 2; ///< <b>(Test)</b> Specifies scale used for slot power limit value. Leave as 0 to set to default. Default is <b>zero</b>.
+ UINT32 SlotPowerLimitValue : 12; ///< <b>(Test)</b> Specifies upper limit on power supplies by slot. Leave as 0 to set to default. Default is <b>zero</b>.
+ //
+ // Gen3 Equalization settings
+ //
+ UINT32 Uptp : 4; ///< <b>(Test)</b> Upstream Port Transmitter Preset used during Gen3 Link Equalization. Used for all lanes. Default is <b>5</b>.
+ UINT32 Dptp : 4; ///< <b>(Test)</b> Downstream Port Transmiter Preset used during Gen3 Link Equalization. Used for all lanes. Default is <b>7</b>.
+ /**
+ Forces LTR override to be permanent
+ The default way LTR override works is:
+ rootport uses LTR override values provided by BIOS until connected device sends an LTR message, then it will use values from the message
+ This settings allows force override of LTR mechanism. If it's enabled, then:
+ rootport will use LTR override values provided by BIOS forever; LTR messages sent from connected device will be ignored
+ **/
+ UINT32 ForceLtrOverride : 1;
+ UINT32 EnableCpm : 1; ///< Enables Clock Power Management; even if disabled, CLKREQ# signal can still be controlled by L1 PM substates mechanism
+ UINT32 RsvdBits3 : 8; ///< Reserved Bits
+ /**
+ The number of milliseconds reference code will wait for link to exit Detect state for enabled ports
+ before assuming there is no device and potentially disabling the port.
+ It's assumed that the link will exit detect state before root port initialization (sufficient time
+ elapsed since PLTRST de-assertion) therefore default timeout is zero. However this might be useful
+ if device power-up seqence is controlled by BIOS or a specific device requires more time to detect.
+ In case of non-common clock enabled the default timout is 15ms.
+ <b>Default: 0</b>
+ **/
+ UINT16 DetectTimeoutMs;
+ UINT16 Rsvd2; ///< Reserved bytes
+ UINT32 Rsvd3; ///< Reserved bytes
+} PCH_PCIE_ROOT_PORT_CONFIG;
+
+/**
+ The PCH_PCIE_CONFIG block describes the expected configuration of the PCH PCI Express controllers
+ <b>Revision 1</b>: Init version
+ <b>Revision 2</b>: Deprecate the PCIE RP enable in post mem.
+ <b>Revision 3</b>: Added DetectTimeoutMs parameter per port. The common DetectTimeoutMs is obsolete.
+ <b>Revision 4</b>: Added EnableHotplugSmi parameter per port.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of each PCH PCIe root port.
+ ///
+ PCH_PCIE_ROOT_PORT_CONFIG RootPort[PCH_MAX_PCIE_ROOT_PORTS];
+ ///
+ /// Gen3 Equalization settings for physical PCIe lane, index 0 represents PCIe lane 1, etc.
+ /// Corresponding entries are used when root port EqPh3Method is PchPcieEqStaticCoeff (default).
+ ///
+ PCH_PCIE_EQ_LANE_PARAM EqPh3LaneParam[PCH_MAX_PCIE_ROOT_PORTS];
+ ///
+ /// List of coefficients used during equalization (applicable to both software and hardware EQ)
+ ///
+ PCH_PCIE_EQ_PARAM SwEqCoeffList[PCH_PCIE_SWEQ_COEFFS_MAX];
+ PCH_PCIE_EQ_PARAM Rsvd0[3];
+ ///
+ /// <b>(Test)</b> This member describes whether PCIE root port Port 8xh Decode is enabled. <b>0: Disable</b>; 1: Enable.
+ ///
+ UINT32 EnablePort8xhDecode : 1;
+ ///
+ /// <b>(Test)</b> The Index of PCIe Port that is selected for Port8xh Decode (0 Based)
+ ///
+ UINT32 PchPciePort8xhDecodePortIndex : 5;
+ ///
+ /// This member describes whether the PCI Express Clock Gating for each root port
+ /// is enabled by platform modules. <b>0: Disable</b>; 1: Enable.
+ ///
+ UINT32 DisableRootPortClockGating : 1;
+ ///
+ /// This member describes whether Peer Memory Writes are enabled on the platform. <b>0: Disable</b>; 1: Enable.
+ ///
+ UINT32 EnablePeerMemoryWrite : 1;
+ /**
+ This member allows BIOS to control ICC PLL Shutdown by determining PCIe devices are LTR capable
+ or leaving untouched.
+ - <b>0: Disable, ICC PLL Shutdown is determined by PCIe device LTR capablility.</b>
+ - To allow ICC PLL shutdown if all present PCIe devices are LTR capable or if no PCIe devices are
+ presented for maximum power savings where possible.
+ - To disable ICC PLL shutdown when BIOS detects any non-LTR capable PCIe device for ensuring device
+ functionality.
+ - 1: Enable, To allow ICC PLL shutdown even if some devices do not support LTR capability.
+ **/
+ UINT32 AllowNoLtrIccPllShutdown : 1;
+ /**
+ Compliance Test Mode shall be enabled when using Compliance Load Board.
+ <b>0: Disable</b>, 1: Enable
+ **/
+ UINT32 ComplianceTestMode : 1;
+ /**
+ RpFunctionSwap allows BIOS to use root port function number swapping when root port of function 0 is disabled.
+ A PCIE device can have higher functions only when Function0 exists. To satisfy this requirement,
+ BIOS will always enable Function0 of a device that contains more than 0 enabled root ports.
+ - <b>Enabled: One of enabled root ports get assigned to Function0.</b>
+ This offers no guarantee that any particular root port will be available at a specific DevNr:FuncNr location
+ - Disabled: Root port that corresponds to Function0 will be kept visible even though it might be not used.
+ That way rootport - to - DevNr:FuncNr assignment is constant. This option will impact ports 1, 9, 17.
+ NOTE: This option will not work if ports 1, 9, 17 are fused or configured for RST PCIe storage
+ NOTE: Disabling function swap may have adverse impact on power management. This option should ONLY
+ be used when each one of root ports 1, 9, 17:
+ - is configured as PCIe and has correctly configured ClkReq signal, or
+ - does not own any mPhy lanes (they are configured as SATA or USB)
+ **/
+ UINT32 RpFunctionSwap : 1;
+
+ UINT32 RsvdBits0 : 21;
+ /**
+ @deprecated since revision 3, substituted by per-port timeout parameter
+ The number of milliseconds reference code will wait for link to exit Detect state for enabled ports
+ before assuming there is no device and potentially disabling the port.
+ It's assumed that the link will exit detect state before root port initialization (sufficient time
+ elapsed since PLTRST de-assertion) therefore default timeout is zero. However this might be useful
+ if device power-up sequence is controlled by BIOS or a specific device requires more time to detect.
+ I case of non-common clock enabled the default timeout is 15ms.
+ <b>Default: 0</b>
+ **/
+ UINT16 DetectTimeoutMs;
+ UINT16 Rsvd1; ///< Reserved bytes
+ /**
+ PCIe device override table
+ The PCIe device table is being used to override PCIe device ASPM settings.
+ This is a pointer points to a 32bit address. And it's only used in PostMem phase.
+ Please refer to PCH_PCIE_DEVICE_OVERRIDE structure for the table.
+ Last entry VendorId must be 0.
+ The prototype of this policy is:
+ PCH_PCIE_DEVICE_OVERRIDE *PcieDeviceOverrideTablePtr;
+ **/
+ UINT32 PcieDeviceOverrideTablePtr;
+
+} PCH_PCIE_CONFIG;
+
+/**
+ The PCH_PCIE_RP_PREMEM_CONFIG block describes early configuration of the PCH PCI Express controllers
+ Revision 1: Init version
+ Add RpEnable in premem phase.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Root Port enabling mask.
+ Bit0 presents RP1, Bit1 presents RP2, and so on.
+ 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 RpEnabledMask;
+} PCH_PCIE_RP_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PCH_PCIE_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h
new file mode 100644
index 0000000000..f483987c97
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h
@@ -0,0 +1,215 @@
+/** @file
+ Power Management policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PM_CONFIG_H_
+#define _PM_CONFIG_H_
+
+#define PM_CONFIG_REVISION 4
+extern EFI_GUID gPmConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure allows to customize PCH wake up capability from S5 or DeepSx by WOL, LAN, PCIE wake events.
+**/
+typedef struct {
+ /**
+ Corresponds to the PME_B0_S5_DIS bit in the General PM Configuration B (GEN_PMCON_B) register.
+ When set to 1, this bit blocks wake events from PME_B0_STS in S5, regardless of the state of PME_B0_EN.
+ When cleared (default), wake events from PME_B0_STS are allowed in S5 if PME_B0_EN = 1. <b>0: Disable</b>; 1: Enable.
+ **/
+ UINT32 PmeB0S5Dis : 1;
+ UINT32 WolEnableOverride : 1; ///< Corresponds to the "WOL Enable Override" bit in the General PM Configuration B (GEN_PMCON_B) register. 0: Disable; <b>1: Enable</b>.
+ UINT32 PcieWakeFromDeepSx : 1; ///< Determine if enable PCIe to wake from deep Sx. <b>0: Disable</b>; 1: Enable.
+ UINT32 WoWlanEnable : 1; ///< Determine if WLAN wake from Sx, corresponds to the "HOST_WLAN_PP_EN" bit in the PWRM_CFG3 register. <b>0: Disable</b>; 1: Enable.
+ UINT32 WoWlanDeepSxEnable : 1; ///< Determine if WLAN wake from DeepSx, corresponds to the "DSX_WLAN_PP_EN" bit in the PWRM_CFG3 register. <b>0: Disable</b>; 1: Enable.
+ UINT32 LanWakeFromDeepSx : 1; ///< Determine if enable LAN to wake from deep Sx. 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 26;
+} PCH_WAKE_CONFIG;
+
+typedef enum {
+ PchDeepSxPolDisable,
+ PchDpS5BatteryEn,
+ PchDpS5AlwaysEn,
+ PchDpS4S5BatteryEn,
+ PchDpS4S5AlwaysEn,
+ PchDpS3S4S5BatteryEn,
+ PchDpS3S4S5AlwaysEn
+} PCH_DEEP_SX_CONFIG;
+
+typedef enum {
+ PchSlpS360us,
+ PchSlpS31ms,
+ PchSlpS350ms,
+ PchSlpS32s
+} PCH_SLP_S3_MIN_ASSERT;
+
+typedef enum {
+ PchSlpS4PchTime, ///< The time defined in PCH EDS Power Sequencing and Reset Signal Timings table
+ PchSlpS41s,
+ PchSlpS42s,
+ PchSlpS43s,
+ PchSlpS44s
+} PCH_SLP_S4_MIN_ASSERT;
+
+typedef enum {
+ PchSlpSus0ms,
+ PchSlpSus500ms,
+ PchSlpSus1s,
+ PchSlpSus4s
+} PCH_SLP_SUS_MIN_ASSERT;
+
+typedef enum {
+ PchSlpA0ms,
+ PchSlpA4s,
+ PchSlpA98ms,
+ PchSlpA2s
+} PCH_SLP_A_MIN_ASSERT;
+
+/**
+ The PCH_PM_CONFIG block describes expected miscellaneous power management settings.
+ The PowerResetStatusClear field would clear the Power/Reset status bits, please
+ set the bits if you want PCH Init driver to clear it, if you want to check the
+ status later then clear the bits.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Deprecate CapsuleResetType and the capsule update always uses warmreset cycle.
+ <b>Revision 3</b>:
+ - Added SlpS0VmEnable.
+ <b>Revision 4</b>
+ - Deprecate PciePllSsc and moved to PCH_HSIO_PCIE_PREMEM_CONFIG
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ PCH_WAKE_CONFIG WakeConfig; ///< Specify Wake Policy
+ UINT32 PchDeepSxPol : 4; ///< Deep Sx Policy. Refer to PCH_DEEP_SX_CONFIG for each value. Default is <b>PchDeepSxPolDisable</b>.
+ UINT32 PchSlpS3MinAssert : 4; ///< SLP_S3 Minimum Assertion Width Policy. Refer to PCH_SLP_S3_MIN_ASSERT for each value. Default is <b>PchSlpS350ms</b>.
+ UINT32 PchSlpS4MinAssert : 4; ///< SLP_S4 Minimum Assertion Width Policy. Refer to PCH_SLP_S4_MIN_ASSERT for each value. Default is <b>PchSlpS44s</b>.
+ UINT32 PchSlpSusMinAssert : 4; ///< SLP_SUS Minimum Assertion Width Policy. Refer to PCH_SLP_SUS_MIN_ASSERT for each value. Default is <b>PchSlpSus4s</b>.
+ UINT32 PchSlpAMinAssert : 4; ///< SLP_A Minimum Assertion Width Policy. Refer to PCH_SLP_A_MIN_ASSERT for each value. Default is <b>PchSlpA2s</b>.
+ UINT32 RsvdBits0 : 12;
+ /**
+ This member describes whether or not the LPC ClockRun feature of PCH should
+ be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 LpcClockRun : 1;
+ UINT32 SlpStrchSusUp : 1; ///< <b>0: Disable</b>; 1: Enable SLP_X Stretching After SUS Well Power Up
+ /**
+ Enable/Disable SLP_LAN# Low on DC Power. 0: Disable; <b>1: Enable</b>.
+ Configure On DC PHY Power Diable according to policy SlpLanLowDc.
+ When this is enabled, SLP_LAN# will be driven low when ACPRESENT is low.
+ This indicates that LAN PHY should be powered off on battery mode.
+ This will override the DC_PP_DIS setting by WolEnableOverride.
+ **/
+ UINT32 SlpLanLowDc : 1;
+ /**
+ PCH power button override period.
+ 000b-4s, 001b-6s, 010b-8s, 011b-10s, 100b-12s, 101b-14s
+ <b>Default is 0: 4s</b>
+ **/
+ UINT32 PwrBtnOverridePeriod : 3;
+ /**
+ <b>(Test)</b>
+ Disable/Enable PCH to CPU enery report feature. <b>0: Disable</b>; 1: Enable.
+ Enery Report is must have feature. Wihtout Energy Report, the performance report
+ by workloads/benchmarks will be unrealistic because PCH's energy is not being accounted
+ in power/performance management algorithm.
+ If for some reason PCH energy report is too high, which forces CPU to try to reduce
+ its power by throttling, then it could try to disable Energy Report to do first debug.
+ This might be due to energy scaling factors are not correct or the LPM settings are not
+ kicking in.
+ **/
+ UINT32 DisableEnergyReport : 1;
+ /**
+ When set to Disable, PCH will internal pull down AC_PRESENT in deep SX and during G3 exit.
+ When set to Enable, PCH will not pull down AC_PRESENT.
+ This setting is ignored when DeepSx is not supported.
+ Default is <b>0:Disable</b>
+ **/
+ UINT32 DisableDsxAcPresentPulldown : 1;
+ /**
+ <b>(Test)</b>
+ When set to true, this bit disallows host reads to PMC XRAM.
+ BIOS must set this bit (to disable and lock the feature) prior to passing control to OS
+ 0:Disable, <b>1:Enable</b>
+ **/
+ UINT32 PmcReadDisable : 1;
+ /**
+ @deprecated This determines the type of reset issued during the capsule update process by UpdateCapsule().
+ Always Warm reset.
+ **/
+ UINT32 CapsuleResetType : 1;
+ /**
+ Power button native mode disable.
+ While FALSE, the PMC's power button logic will act upon the input value from the GPIO unit, as normal.
+ While TRUE, this will result in the PMC logic constantly seeing the power button as de-asserted.
+ <b>Default is FALSE.</b>
+ **/
+ UINT32 DisableNativePowerButton : 1;
+ /**
+ Indicates whether SLP_S0# is to be asserted when PCH reaches idle state.
+ When set to one SLP_S0# will be asserted in idle state.
+ When set to zero SLP_S0# will not toggle and is always drivern high.
+ 0:Disable, <b>1:Enable</b>
+
+ @warning: In SKL PCH VCCPRIM_CORE must NOT be reduced based on SLP_S0# being asserted.
+ If a platform is using SLP_S0 to lower PCH voltage the below policy must be disabled.
+ **/
+ UINT32 SlpS0Enable : 1;
+ UINT32 MeWakeSts : 1; ///< Clear the ME_WAKE_STS bit in the Power and Reset Status (PRSTS) register. 0: Disable; <b>1: Enable</b>.
+ UINT32 WolOvrWkSts : 1; ///< Clear the WOL_OVR_WK_STS bit in the Power and Reset Status (PRSTS) register. 0: Disable; <b>1: Enable</b>.
+ /**
+ Set true to enable TCO timer.
+ When FALSE, it disables PCH ACPI timer, and stops TCO timer.
+ @note: This will have significant power impact when it's enabled.
+ If TCO timer is disabled, uCode ACPI timer emulation must be enabled,
+ and WDAT table must not be exposed to the OS.
+ <b>0: Disable</b>, 1: Enable
+ **/
+ UINT32 EnableTcoTimer : 1;
+ /**
+ Indicates platform has support for VCCPrim_Core Voltage Margining in SLP_S0# asserted state.
+ 0: Disable, <b>1: Enable</b>
+ **/
+ UINT32 SlpS0VmEnable : 1;
+ UINT32 RsvdBits1 : 16;
+ /**
+ Reset Power Cycle Duration could be customized in the unit of second. Please refer to EDS
+ for all support settings. PCH HW default is 4 seconds, and range is 1~4 seconds, where
+ <b>0 is default</b>, 1 is 1 second, 2 is 2 seconds, ... 4 is 4 seconds.
+ And make sure the setting correct, which never less than the following register.
+ - GEN_PMCON_B.SLP_S3_MIN_ASST_WDTH
+ - GEN_PMCON_B.SLP_S4_MIN_ASST_WDTH
+ - PWRM_CFG.SLP_A_MIN_ASST_WDTH
+ - PWRM_CFG.SLP_LAN_MIN_ASST_WDTH
+ **/
+ UINT8 PchPwrCycDur;
+ /**
+ @deprecated since revision 4
+ Specifies the Pcie Pll Spread Spectrum Percentage
+ The value of this policy is in 1/10th percent units.
+ Valid spread range is 0-20. A value of 0xFF is reserved for AUTO.
+ A value of 0 is SSC of 0.0%. A value of 20 is SSC of 2.0%
+ The default is <b>0xFF: AUTO - No BIOS override</b>.
+ **/
+ UINT8 PciePllSsc;
+ UINT8 Rsvd0[2]; ///< Reserved bytes
+
+} PCH_PM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PM_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h
new file mode 100644
index 0000000000..d8b9cf6145
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h
@@ -0,0 +1,34 @@
+/** @file
+ Port 61h policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PORT_61_CONFIG_H_
+#define _PORT_61_CONFIG_H_
+
+#define PORT_61_CONFIG_REVISION 1
+extern EFI_GUID gPort61ConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure is used for the emulation feature for Port61h read. The port is trapped
+ and the SMI handler will toggle bit4 according to the handler's internal state.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b> the emulation
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_PORT61H_SMM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PORT_61_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h
new file mode 100644
index 0000000000..0dc76e0c23
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h
@@ -0,0 +1,193 @@
+/** @file
+ Sata policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SATA_CONFIG_H_
+#define _SATA_CONFIG_H_
+
+#define SATA_CONFIG_REVISION 4
+extern EFI_GUID gSataConfigGuid;
+
+#pragma pack (push,1)
+
+typedef enum {
+ PchSataModeAhci,
+ PchSataModeRaid,
+ PchSataModeMax
+} PCH_SATA_MODE;
+
+enum {
+ PchSataOromDelay2sec,
+ PchSataOromDelay4sec,
+ PchSataOromDelay6sec,
+ PchSataOromDelay8sec
+} PCH_SATA_OROM_DELAY;
+
+typedef enum {
+ PchSataSpeedDefault,
+ PchSataSpeedGen1,
+ PchSataSpeedGen2,
+ PchSataSpeedGen3
+} PCH_SATA_SPEED;
+
+/**
+ This structure configures the features, property, and capability for each SATA port.
+**/
+typedef struct {
+ /**
+ Enable SATA port.
+ It is highly recommended to disable unused ports for power savings
+ **/
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b>
+ UINT32 HotPlug : 1; ///< <b>0: Disable</b>; 1: Enable
+ UINT32 InterlockSw : 1; ///< <b>0: Disable</b>; 1: Enable
+ UINT32 External : 1; ///< <b>0: Disable</b>; 1: Enable
+ UINT32 SpinUp : 1; ///< <b>0: Disable</b>; 1: Enable the COMRESET initialization Sequence to the device
+ UINT32 SolidStateDrive : 1; ///< <b>0: HDD</b>; 1: SSD
+ UINT32 DevSlp : 1; ///< <b>0: Disable</b>; 1: Enable DEVSLP on the port
+ UINT32 EnableDitoConfig : 1; ///< <b>0: Disable</b>; 1: Enable DEVSLP Idle Timeout settings (DmVal, DitoVal)
+ UINT32 DmVal : 4; ///< DITO multiplier. Default is <b>15</b>.
+ UINT32 DitoVal : 10; ///< DEVSLP Idle Timeout (DITO), Default is <b>625</b>.
+ /**
+ Support zero power ODD <b>0: Disable</b>, 1: Enable.
+ This is also used to disable ModPHY dynamic power gate.
+ **/
+ UINT32 ZpOdd : 1;
+ UINT32 RsvdBits0 : 9; ///< Reserved fields for future expansion w/o protocol change
+} PCH_SATA_PORT_CONFIG;
+
+/**
+ Rapid Storage Technology settings.
+**/
+typedef struct {
+ UINT32 RaidAlternateId : 1; ///< @deprecated
+ UINT32 Raid0 : 1; ///< 0: Disable; <b>1: Enable</b> RAID0
+ UINT32 Raid1 : 1; ///< 0: Disable; <b>1: Enable</b> RAID1
+ UINT32 Raid10 : 1; ///< 0: Disable; <b>1: Enable</b> RAID10
+ UINT32 Raid5 : 1; ///< 0: Disable; <b>1: Enable</b> RAID5
+ UINT32 Irrt : 1; ///< 0: Disable; <b>1: Enable</b> Intel Rapid Recovery Technology
+ UINT32 OromUiBanner : 1; ///< 0: Disable; <b>1: Enable</b> OROM UI and BANNER
+ UINT32 OromUiDelay : 2; ///< <b>00b: 2 secs</b>; 01b: 4 secs; 10b: 6 secs; 11: 8 secs (see: PCH_SATA_OROM_DELAY)
+ UINT32 HddUnlock : 1; ///< 0: Disable; <b>1: Enable</b>. Indicates that the HDD password unlock in the OS is enabled
+ UINT32 LedLocate : 1; ///< 0: Disable; <b>1: Enable</b>. Indicates that the LED/SGPIO hardware is attached and ping to locate feature is enabled on the OS
+ UINT32 IrrtOnly : 1; ///< 0: Disable; <b>1: Enable</b>. Allow only IRRT drives to span internal and external ports
+ UINT32 SmartStorage : 1; ///< 0: Disable; <b>1: Enable</b> RST Smart Storage caching Bit
+ UINT32 LegacyOrom : 1; ///< <b>0: Disable</b>; 1: Enable RST Legacy OROM
+ /**
+ This option allows to configure SATA controller device ID while in RAID mode
+ Choosing Client will allow RST driver loading, RSTe driver will not be able to load
+ Choosing Alternate will not allow RST inbox driver loading in Windows
+ Choosing Server will allow RSTe driver loading, RST driver will not load
+ <b>0: Client</b>; 1: Alternate; 2: Server
+ **/
+ UINT32 RaidDeviceId : 2;
+ UINT32 OptaneMemory : 1; ///< 0: Disable; <b>1: Enable</b> RST Optane(TM) Memory
+ UINT32 RsvdBits0 : 15; ///< Reserved Bits
+} PCH_SATA_RST_CONFIG;
+
+/**
+ This structure describes the details of Intel RST for PCIe Storage remapping
+ Note: In order to use this feature, Intel RST Driver is required
+**/
+typedef struct {
+ /**
+ This member describes whether or not the Intel RST for PCIe Storage remapping should be enabled. <b>0: Disable</b>; 1: Enable.
+ Note 1: If Sata Controller is disabled, PCIe Storage Remapping should be disabled as well
+ Note 2: If PCIe Storage remapping is enabled, the PCH integrated AHCI controllers Class Code is configured as RAID
+ **/
+ UINT32 Enable : 1;
+ /**
+ Intel RST for PCIe Storage remapping - PCIe Port Selection (1-based, <b>0 = autodetect</b>)
+ The supported ports for PCIe Storage remapping is different depend on the platform and cycle router, the assignments are as below:
+ SKL PCH-LP RST PCIe Storage Cycle Router Assignment:
+ i.) RST PCIe Storage Cycle Router 2 -> RP5 - RP8
+ ii.) RST PCIe Storage Cycle Router 3 -> RP9 - RP12
+
+ SKL PCH-H RST PCIe Storage Cycle Router Assignment:
+ i.) RST PCIe Storage Cycle Router 1 -> RP9 - RP12
+ ii.) RST PCIe Storage Cycle Router 2 -> RP13 - RP16
+ iii.) RST PCIe Storage Cycle Router 3 -> RP17 - RP20
+ **/
+ UINT32 RstPcieStoragePort : 5;
+ UINT32 RsvdBits0 : 2; ///< Reserved bit
+ /**
+ PCIe Storage Device Reset Delay in milliseconds (ms), which it guarantees such delay gap is fulfilled
+ before PCIe Storage Device configuration space is accessed after an reset caused by the link disable and enable step.
+ Default value is <b>100ms</b>.
+ **/
+ UINT32 DeviceResetDelay : 8;
+ UINT32 RsvdBits1 : 16; ///< Reserved bits
+
+ UINT32 Rsvd0[2]; ///< Reserved bytes
+} PCH_RST_PCIE_STORAGE_CONFIG;
+
+/**
+ The PCH_SATA_CONFIG block describes the expected configuration of the SATA controllers.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Added LegacyOrom in RST_SATA_RST_CONFIG to force RST Legacy Orom useage
+ <b>Revision 3</b>
+ - Added RaidDeviceId in PCH_SATA_RST_CONFIG to allow choice of RAID device id
+ <b>Revision 4</b>
+ - Added OptaneMemory in PCH_SATA_RST_CONFIG to enable RST optane memory
+**/
+typedef struct {
+ /**
+ This member specifies the revision of the SATA Configuration structure.
+ Any backwards compatible changes to this structure will result in an update in the revision number.
+ **/
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// This member describes whether or not the SATA controllers should be enabled. 0: Disable; <b>1: Enable</b>.
+ ///
+ UINT32 Enable : 1;
+ UINT32 TestMode : 1; ///< <b>(Test)</b> <b>0: Disable</b>; 1: Allow entrance to the PCH SATA test modes
+ UINT32 SalpSupport : 1; ///< 0: Disable; <b>1: Enable</b> Aggressive Link Power Management
+ UINT32 PwrOptEnable : 1; ///< 0: Disable; <b>1: Enable</b> SATA Power Optimizer on PCH side.
+ /**
+ EsataSpeedLimit
+ When enabled, BIOS will configure the PxSCTL.SPD to 2 to limit the eSATA port speed.
+ Please be noted, this setting could be cleared by HBA reset, which might be issued
+ by EFI AHCI driver when POST time, or by SATA inbox driver/RST driver after POST.
+ To support the Speed Limitation when POST, the EFI AHCI driver should preserve the
+ setting before and after initialization. For support it after POST, it's dependent on
+ driver's behavior.
+ <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 EsataSpeedLimit : 1;
+ UINT32 RsvdBits0 : 27; ///< Reserved bits
+
+ /**
+ Determines the system will be configured to which SATA mode (PCH_SATA_MODE). Default is <b>PchSataModeAhci</b>.
+ **/
+ PCH_SATA_MODE SataMode;
+ /**
+ Indicates the maximum speed the SATA controller can support
+ <b>0h: PchSataSpeedDefault</b>; 1h: 1.5 Gb/s (Gen 1); 2h: 3 Gb/s(Gen 2); 3h: 6 Gb/s (Gen 1)
+ **/
+ PCH_SATA_SPEED SpeedLimit;
+ /**
+ This member configures the features, property, and capability for each SATA port.
+ **/
+ PCH_SATA_PORT_CONFIG PortSettings[PCH_MAX_SATA_PORTS];
+ PCH_SATA_RST_CONFIG Rst; ///< Setting applicable to Rapid Storage Technology
+ /**
+ This member describes the details of implementation of Intel RST for PCIe Storage remapping (Intel RST Driver is required)
+ **/
+ PCH_RST_PCIE_STORAGE_CONFIG RstPcieStorageRemap[PCH_MAX_RST_PCIE_STORAGE_CR];
+} PCH_SATA_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SATA_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h
new file mode 100644
index 0000000000..05a2f5dbfa
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h
@@ -0,0 +1,61 @@
+/** @file
+ Scs policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SCS_CONFIG_H_
+#define _SCS_CONFIG_H_
+
+#define SCS_CONFIG_REVISION 1
+extern EFI_GUID gScsConfigGuid;
+
+#pragma pack (push,1)
+
+typedef enum {
+ PchScsSdDisabled = 0,
+ PchScsSdcardMode = 2
+} PCH_SCS_DEV_SD_MODE;
+
+typedef enum {
+ DriverStrength33Ohm = 0,
+ DriverStrength40Ohm,
+ DriverStrength50Ohm
+} PCH_SCS_EMMC_DRIVER_STRENGTH;
+
+///
+/// The PCH_SCS_CONFIG block describes Storage and Communication Subsystem (SCS) settings for PCH.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ UINT32 ScsEmmcEnabled : 2; ///< Determine if eMMC is enabled - 0: Disabled, <b>1: Enabled</b>.
+ UINT32 ScsEmmcHs400Enabled : 1; ///< Determine eMMC HS400 Mode if ScsEmmcEnabled - <b>0: Disabled</b>, 1: Enabled
+ /**
+ Determine if HS400 Training is required, set to FALSE if Hs400 Data is valid. <b>0: Disabled</b>, 1: Enabled.
+ First Boot or CMOS clear, system boot with Default settings, set tuning required.
+ Subsequent Boots, Get Variable 'Hs400TuningData'
+ - if failed to get variable, set tuning required
+ - if passed, retrieve Hs400DataValid, Hs400RxStrobe1Dll and Hs400TxDataDll from variable. Set tuning not required.
+ - if driver strength value changes (ScsEmmcHs400DriverStrength) re-tuning is required.
+ **/
+ UINT32 ScsEmmcHs400TuningRequired : 1;
+ UINT32 ScsEmmcHs400DllDataValid : 1; ///< Set if HS400 Tuning Data Valid
+ UINT32 ScsEmmcHs400RxStrobeDll1 : 7; ///< Rx Strobe Delay Control - Rx Strobe Delay DLL 1 (HS400 Mode)
+ UINT32 ScsEmmcHs400TxDataDll : 7; ///< Tx Data Delay Control 1 - Tx Data Delay (HS400 Mode)
+ UINT32 ScsEmmcHs400DriverStrength : 3; ///< I/O driver strength: 0 - 33 Ohm, <b>1 - 40 Ohm</b>, 2 - 50 Ohm
+ UINT32 ScsSdSwitch : 3; ///< Determine the operating mode of SDHC. Refer to PCH_SCS_DEV_SD_MODE for each value - 0: Disabled, <b>2: SDCard</b>.
+ UINT32 RsvdBits : 7;
+ UINT32 Rsvd0; ///< Reserved bytes
+} PCH_SCS_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SCS_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h
new file mode 100644
index 0000000000..5caa24310a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h
@@ -0,0 +1,56 @@
+/** @file
+ Serial IO policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SERIAL_IO_CONFIG_H_
+#define _SERIAL_IO_CONFIG_H_
+
+#define SERIAL_IO_CONFIG_REVISION 1
+extern EFI_GUID gSerialIoConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_SERIAL_IO_CONFIG block provides the configurations to set the Serial IO controllers
+ to Acpi devices or Pci controllers, and also set the interrupt type to Acpi or Pci
+ through Policy. It also provides to configure the I2c0 and I2c1 voltage
+ to 1.8v or 3.3v by platform setting.
+ Please refer to PeiDxeSmmPchSerialIoLib.h for definition of device numbers and enum values for the below fields
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ 0: Disabled; 1: ACPI Mode; <b>2: PCI Mode</b>; 3: Hidden mode, 4: Legacy UART mode, 5: Skip Init
+ @note: Considering the PcdSerialIoUartDebugEnable and PcdSerialIoUartNumber for all SerialIo UARTx,
+ the PCD is more meaningful to represent the board design. It means, if PcdSerialIoUartDebugEnable is not 0,
+ the board is designed to use the SerialIo UART for debug message and the PcdSerialIoUartNumber is dedicated
+ to be Debug UART usage. Therefore, it should grayout the option from setup menu since no other options
+ available for this UART controller on this board, and also override the policy default accordingly.
+ While PcdSerialIoUartDebugEnable is 0, then it's allowed to configure the UART controller by policy.
+ @note: While DevMode is set to 5 (Skip Init), BIOS will not initialize this controller. GPIO and PSF configuration is skipped.
+ Platform is resonsible for configuring this controller. If platform initializes the Serial IO controller in
+ Hidden Mode, it MUST follow the predefined BAR address for the controller.
+ **/
+ UINT8 DevMode[PCH_SERIALIO_MAX_CONTROLLERS];
+ UINT8 Gpio; ///< 0: Disabled; <b>1: Enabled</b>.
+ UINT8 I2cVoltage[PCH_SERIALIO_MAX_I2C_CONTROLLERS]; ///< Selects the IO voltage for I2C controllers. It can be 1.8v or 3.3v. <b>0: PchSerialIoIs33V</b>; 1: PchSerialIoIs18V.
+ UINT8 SpiCsPolarity[PCH_SERIALIO_MAX_SPI_CONTROLLERS]; ///< Selects SPI ChipSelect signal polarity, <b>0=active low</b>.
+ UINT8 UartHwFlowCtrl[PCH_SERIALIO_MAX_UART_CONTROLLERS]; ///< Enables UART hardware flow control, CTS and RTS lines, <b>0:disabled</b>, 1:enabled
+ UINT8 Rsvd0[1]; ///< Bytes reserved for reuse when new fields are added to struct
+ UINT32 DebugUartNumber : 2; ///< UART number for debug purpose. 0:UART0, 1: UART1, <b>2:UART2</b>
+ UINT32 EnableDebugUartAfterPost : 1; ///< Enable debug UART controller after post. 0: diabled, <b>1: enabled</b>
+ UINT32 RsvdBits0 : 29;
+} PCH_SERIAL_IO_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SERIAL_IO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h
new file mode 100644
index 0000000000..b64579cd92
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h
@@ -0,0 +1,48 @@
+/** @file
+ Serial IRQ policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SERIAL_IRQ_CONFIG_H_
+#define _SERIAL_IRQ_CONFIG_H_
+
+#define SERIAL_IRQ_CONFIG_REVISION 1
+extern EFI_GUID gSerialIrqConfigGuid;
+
+#pragma pack (push,1)
+
+typedef enum {
+ PchQuietMode,
+ PchContinuousMode
+} PCH_SIRQ_MODE;
+///
+/// Refer to PCH EDS for the details of Start Frame Pulse Width in Continuous and Quiet mode
+///
+typedef enum {
+ PchSfpw4Clk,
+ PchSfpw6Clk,
+ PchSfpw8Clk
+} PCH_START_FRAME_PULSE;
+
+///
+/// The PCH_LPC_SIRQ_CONFIG block describes the expected configuration of the PCH for Serial IRQ.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 SirqEnable : 1; ///< Determines if enable Serial IRQ. 0: Disable; <b>1: Enable</b>.
+ UINT32 SirqMode : 2; ///< Serial IRQ Mode Select. Refer to PCH_SIRQ_MODE for each value. <b>0: quiet mode</b> 1: continuous mode.
+ UINT32 StartFramePulse : 3; ///< Start Frame Pulse Width. Refer to PCH_START_FRAME_PULSE for each value. Default is <b>PchSfpw4Clk</b>.
+ UINT32 RsvdBits0 : 26; ///< Reserved bits
+} PCH_LPC_SIRQ_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SERIAL_IRQ_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h
new file mode 100644
index 0000000000..78ac72aa87
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h
@@ -0,0 +1,56 @@
+/** @file
+ Smbus policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SMBUS_CONFIG_H_
+#define _SMBUS_CONFIG_H_
+
+#define SMBUS_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gSmbusPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+#define PCH_MAX_SMBUS_RESERVED_ADDRESS 128
+
+///
+/// The SMBUS_CONFIG block lists the reserved addresses for non-ARP capable devices in the platform.
+///
+typedef struct {
+ /**
+ Revision 1: Init version
+ **/
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This member describes whether or not the SMBus controller of PCH should be enabled.
+ 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 Enable : 1;
+ UINT32 ArpEnable : 1; ///< Enable SMBus ARP support, <b>0: Disable</b>; 1: Enable.
+ UINT32 DynamicPowerGating : 1; ///< <b>(Test)</b> <b>Disable</b> or Enable Smbus dynamic power gating.
+ ///
+ /// <b>(Test)</b> SPD Write Disable, 0: leave SPD Write Disable bit; <b>1: set SPD Write Disable bit.</b>
+ /// For security recommendations, SPD write disable bit must be set.
+ ///
+ UINT32 SpdWriteDisable : 1;
+ UINT32 RsvdBits0 : 28; ///< Reserved bits
+ UINT16 SmbusIoBase; ///< SMBUS Base Address (IO space). Default is <b>0xEFA0</b>.
+ UINT8 Rsvd0; ///< Reserved bytes
+ UINT8 NumRsvdSmbusAddresses; ///< The number of elements in the RsvdSmbusAddressTable.
+ /**
+ Array of addresses reserved for non-ARP-capable SMBus devices.
+ **/
+ UINT8 RsvdSmbusAddressTable[PCH_MAX_SMBUS_RESERVED_ADDRESS];
+} PCH_SMBUS_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SMBUS_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h
new file mode 100644
index 0000000000..688fa314cb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h
@@ -0,0 +1,38 @@
+/** @file
+ Spi policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SPI_CONFIG_H_
+#define _SPI_CONFIG_H_
+
+#define SPI_CONFIG_REVISION 1
+extern EFI_GUID gSpiConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to SPI.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Force to show SPI controller.
+ <b>0: FALSE</b>, 1: TRUE
+ NOTE: For Windows OS, it MUST BE false. It's optional for other OSs.
+ **/
+ UINT32 ShowSpiController : 1;
+ UINT32 RsvdBits : 31; ///< Reserved bits
+} PCH_SPI_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SPI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h
new file mode 100644
index 0000000000..8963da6ee7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h
@@ -0,0 +1,176 @@
+/** @file
+ Thermal policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _THERMAL_CONFIG_H_
+#define _THERMAL_CONFIG_H_
+
+#define THERMAL_CONFIG_REVISION 1
+extern EFI_GUID gThermalConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure lists PCH supported throttling register setting for custimization.
+ When the SuggestedSetting is enabled, the customized values are ignored.
+**/
+typedef struct {
+ UINT32 T0Level : 9; ///< Custimized T0Level value. If SuggestedSetting is used, this setting is ignored.
+ UINT32 T1Level : 9; ///< Custimized T1Level value. If SuggestedSetting is used, this setting is ignored.
+ UINT32 T2Level : 9; ///< Custimized T2Level value. If SuggestedSetting is used, this setting is ignored.
+ UINT32 TTEnable : 1; ///< Enable the thermal throttle function. If SuggestedSetting is used, this settings is ignored.
+ /**
+ When set to 1 and the programmed GPIO pin is a 1, then PMSync state 13 will force at least T2 state.
+ If SuggestedSetting is used, this setting is ignored.
+ **/
+ UINT32 TTState13Enable : 1;
+ /**
+ When set to 1, this entire register (TL) is locked and remains locked until the next platform reset.
+ If SuggestedSetting is used, this setting is ignored.
+ **/
+ UINT32 TTLock : 1;
+ UINT32 SuggestedSetting : 1; ///< 0: Disable; <b>1: Enable</b> suggested representative values.
+ /**
+ ULT processors support thermal management and cross thermal throttling between the processor package
+ and LP PCH. The PMSYNC message from PCH to CPU includes specific bit fields to update the PCH
+ thermal status to the processor which is factored into the processor throttling.
+ Enable/Disable PCH Cross Throttling; 0: Disabled, 1: <b>Enabled</b>.
+ **/
+ UINT32 PchCrossThrottling : 1;
+ UINT32 Rsvd0; ///< Reserved bytes
+} THERMAL_THROTTLE_LEVELS;
+
+/**
+ This structure allows to customize DMI HW Autonomous Width Control for Thermal and Mechanical spec design.
+ When the SuggestedSetting is enabled, the customized values are ignored.
+**/
+typedef struct {
+ UINT32 DmiTsawEn : 1; ///< DMI Thermal Sensor Autonomous Width Enable
+ UINT32 SuggestedSetting : 1; ///< 0: Disable; <b>1: Enable</b> suggested representative values
+ UINT32 RsvdBits0 : 6; ///< Reserved bits
+ UINT32 TS0TW : 2; ///< Thermal Sensor 0 Target Width
+ UINT32 TS1TW : 2; ///< Thermal Sensor 1 Target Width
+ UINT32 TS2TW : 2; ///< Thermal Sensor 2 Target Width
+ UINT32 TS3TW : 2; ///< Thermal Sensor 3 Target Width
+ UINT32 RsvdBits1 : 16; ///< Reserved bits
+} DMI_HW_WIDTH_CONTROL;
+
+/**
+ This structure lists PCH supported SATA thermal throttling register setting for custimization.
+ The settings is programmed through SATA Index/Data registers.
+ When the SuggestedSetting is enabled, the customized values are ignored.
+**/
+typedef struct {
+ UINT32 P0T1M : 2; ///< Port 0 T1 Multipler
+ UINT32 P0T2M : 2; ///< Port 0 T2 Multipler
+ UINT32 P0T3M : 2; ///< Port 0 T3 Multipler
+ UINT32 P0TDisp : 2; ///< Port 0 Tdispatch
+
+ UINT32 P1T1M : 2; ///< Port 1 T1 Multipler
+ UINT32 P1T2M : 2; ///< Port 1 T2 Multipler
+ UINT32 P1T3M : 2; ///< Port 1 T3 Multipler
+ UINT32 P1TDisp : 2; ///< Port 1 Tdispatch
+
+ UINT32 P0Tinact : 2; ///< Port 0 Tinactive
+ UINT32 P0TDispFinit : 1; ///< Port 0 Alternate Fast Init Tdispatch
+ UINT32 P1Tinact : 2; ///< Port 1 Tinactive
+ UINT32 P1TDispFinit : 1; ///< Port 1 Alternate Fast Init Tdispatch
+ UINT32 SuggestedSetting : 1; ///< 0: Disable; <b>1: Enable</b> suggested representative values
+ UINT32 RsvdBits0 : 9; ///< Reserved bits
+} SATA_THERMAL_THROTTLE;
+
+/**
+ This structure configures PCH memory throttling thermal sensor GPIO PIN settings
+**/
+typedef struct {
+ /**
+ GPIO PM_SYNC enable, 0:Diabled, 1:<b>Enabled</b>
+ When enabled, RC will overrides the selected GPIO native mode.
+ For GPIO_C, PinSelection 0: CPU_GP_0 (default) or 1: CPU_GP_1
+ For GPIO_D, PinSelection 0: CPU_GP_3 (default) or 1: CPU_GP_2
+ For SKL: CPU_GP_0 is GPP_E3, CPU_GP_1 is GPP_E7, CPU_GP_2 is GPP_B3, CPU_GP_3 is GPP_B4.
+ **/
+ UINT32 PmsyncEnable : 1;
+ UINT32 C0TransmitEnable : 1; ///< GPIO Transmit enable in C0 state, 0:Disabled, 1:<b>Enabled</b>
+ UINT32 PinSelection : 1; ///< GPIO Pin assignment selection, <b>0: default</b>, 1: secondary
+ UINT32 RsvdBits0 : 29;
+} TS_GPIO_PIN_SETTING;
+
+enum PCH_PMSYNC_GPIO_X_SELECTION {
+ TsGpioC,
+ TsGpioD,
+ MaxTsGpioPin
+};
+
+/**
+ This structure supports an external memory thermal sensor (TS-on-DIMM or TS-on-Board).
+**/
+typedef struct {
+ /**
+ This will enable PCH memory throttling.
+ While this policy is enabled, must also enable EnableExtts in SA policy.
+ <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Enable : 1;
+ UINT32 RsvdBits0 : 31;
+ /**
+ GPIO_C and GPIO_D selection for memory throttling.
+ It's strongly recommended to choose GPIO_C and GPIO_D for memory throttling feature,
+ and route EXTTS# accordingly.
+ **/
+ TS_GPIO_PIN_SETTING TsGpioPinSetting[2];
+} PCH_MEMORY_THROTTLING;
+
+/**
+ The PCH_THERMAL_CONFIG block describes the expected configuration of the PCH for Thermal.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This field reports the status of Thermal Device. When it reports ThermalDevice
+ is disabled, the PCI configuration space of thermal device will be hidden by
+ setting TCFD and PCR[PSF2] TRH PCIEN[8] prior to end of POST.
+ **/
+ UINT32 ThermalDeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled in PCI mode</b>, 2: Enabled in ACPI mode
+ UINT32 TsmicLock : 1; ///< This locks down "SMI Enable on Alert Thermal Sensor Trip". 0: Disabled, 1: <b>Enabled</b>.
+ UINT32 RsvdBits0 : 29;
+ /**
+ This field decides the settings of Thermal throttling. When the Suggested Setting
+ is enabled, PCH RC will use the suggested representative values.
+ **/
+ THERMAL_THROTTLE_LEVELS TTLevels;
+ /**
+ This field decides the settings of DMI throttling. When the Suggested Setting
+ is enabled, PCH RC will use the suggested representative values.
+ **/
+ DMI_HW_WIDTH_CONTROL DmiHaAWC;
+ /**
+ This field decides the settings of Sata thermal throttling. When the Suggested Setting
+ is enabled, PCH RC will use the suggested representative values.
+ **/
+ SATA_THERMAL_THROTTLE SataTT;
+ /**
+ Memory Thermal Management settings
+ **/
+ PCH_MEMORY_THROTTLING MemoryThrottling;
+ /**
+ This field decides the temperature, default is <b>zero</b>.
+ - 0x00 is the hottest
+ - 0x1FF is the lowest temperature
+ **/
+ UINT16 PchHotLevel;
+ UINT8 Rsvd0[6];
+} PCH_THERMAL_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _THERMAL_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h
new file mode 100644
index 0000000000..5455c40514
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h
@@ -0,0 +1,35 @@
+/** @file
+ Trace Hub policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _TRACEHUB_CONFIG_H_
+#define _TRACEHUB_CONFIG_H_
+
+#define TRACEHUB_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gTraceHubPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_TRACE_HUB_CONFIG block describes TraceHub settings for PCH.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 EnableMode : 2; ///< 0 = Disable <b> 2 = Host Debugger enabled </b>
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+ UINT32 MemReg0Size; ///< Default is <b>0 (none)</b>.
+ UINT32 MemReg1Size; ///< Default is <b>0 (none)</b>.
+} PCH_TRACE_HUB_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _TRACEHUB_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h
new file mode 100644
index 0000000000..c2cef0aa43
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h
@@ -0,0 +1,233 @@
+/** @file
+ USB policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _USB_CONFIG_H_
+#define _USB_CONFIG_H_
+
+#define USB_CONFIG_REVISION 2
+extern EFI_GUID gUsbConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// Overcurrent pins, the values match the setting of PCH EDS, please refer to PCH EDS for more details
+///
+typedef enum {
+ PchUsbOverCurrentPin0 = 0,
+ PchUsbOverCurrentPin1,
+ PchUsbOverCurrentPin2,
+ PchUsbOverCurrentPin3,
+ PchUsbOverCurrentPin4,
+ PchUsbOverCurrentPin5,
+ PchUsbOverCurrentPin6,
+ PchUsbOverCurrentPin7,
+ PchUsbOverCurrentPinSkip,
+ PchUsbOverCurrentPinMax
+} PCH_USB_OVERCURRENT_PIN;
+
+///
+/// The location of the USB connectors. This information is use to decide eye diagram tuning value for Usb 2.0 motherboard trace.
+///
+enum PCH_USB_PORT_LOCATION{
+ PchUsbPortLocationBackPanel = 0,
+ PchUsbPortLocationFrontPanel,
+ PchUsbPortLocationDock,
+ PchUsbPortLocationMiniPciE,
+ PchUsbPortLocationFlex,
+ PchUsbPortLocationInternalTopology,
+ PchUsbPortLocationSkip,
+ PchUsbPortLocationMax
+};
+
+
+/**
+ This structure configures per USB2 AFE settings.
+ It allows to setup the port parameters.
+**/
+typedef struct {
+/** Per Port HS Preemphasis Bias (PERPORTPETXISET)
+ 000b - 0mV
+ 001b - 11.25mV
+ 010b - 16.9mV
+ 011b - 28.15mV
+ 100b - 28.15mV
+ 101b - 39.35mV
+ 110b - 45mV
+ 111b - 56.3mV
+**/
+ UINT8 Petxiset;
+/** Per Port HS Transmitter Bias (PERPORTTXISET)
+ 000b - 0mV
+ 001b - 11.25mV
+ 010b - 16.9mV
+ 011b - 28.15mV
+ 100b - 28.15mV
+ 101b - 39.35mV
+ 110b - 45mV
+ 111b - 56.3mV
+**/
+ UINT8 Txiset;
+/**
+ Per Port HS Transmitter Emphasis (IUSBTXEMPHASISEN)
+ 00b - Emphasis OFF
+ 01b - De-emphasis ON
+ 10b - Pre-emphasis ON
+ 11b - Pre-emphasis & De-emphasis ON
+**/
+ UINT8 Predeemp;
+/**
+ Per Port Half Bit Pre-emphasis (PERPORTTXPEHALF)
+ 1b - half-bit pre-emphasis
+ 0b - full-bit pre-emphasis
+**/
+ UINT8 Pehalfbit;
+} PCH_USB20_AFE;
+
+/**
+ This structure configures per USB2 port physical settings.
+ It allows to setup the port location and port length, and configures the port strength accordingly.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+ /**
+ These members describe the specific over current pin number of USB 2.0 Port N.
+ It is SW's responsibility to ensure that a given port's bit map is set only for
+ one OC pin Description. USB2 and USB3 on the same combo Port must use the same
+ OC pin (see: PCH_USB_OVERCURRENT_PIN).
+ **/
+ UINT8 OverCurrentPin;
+ UINT8 Rsvd0[3]; ///< Reserved bytes, align to multiple 4.
+ PCH_USB20_AFE Afe; ///< USB2 AFE settings
+ UINT32 Rsvd1[1]; ///< Reserved bytes
+} PCH_USB20_PORT_CONFIG;
+
+/**
+ This structure describes whether the USB3 Port N of PCH is enabled by platform modules.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+ /**
+ These members describe the specific over current pin number of USB 3.0 Port N.
+ It is SW's responsibility to ensure that a given port's bit map is set only for
+ one OC pin Description. USB2 and USB3 on the same combo Port must use the same
+ OC pin (see: PCH_USB_OVERCURRENT_PIN).
+ **/
+ UINT8 OverCurrentPin;
+ UINT8 Rsvd0[3]; ///< Reserved bytes, align to multiple 4
+
+ UINT32 HsioTxDeEmphEnable : 1; ///< Enable the write to USB 3.0 TX Output -3.5dB De-Emphasis Adjustment, <b>0: Disable</b>; 1: Enable.
+ /**
+ USB 3.0 TX Output -3.5dB De-Emphasis Adjustment Setting (ow2tapgen2deemph3p5)
+ HSIO_TX_DWORD5[21:16]
+ <b>Default = 29h</b> (approximately -3.5dB De-Emphasis)
+ **/
+ UINT32 HsioTxDeEmph : 6;
+
+ UINT32 HsioTxDownscaleAmpEnable : 1; ///< Enable the write to USB 3.0 TX Output Downscale Amplitude Adjustment, <b>0: Disable</b>; 1: Enable.
+ /**
+ USB 3.0 TX Output Downscale Amplitude Adjustment (orate01margin)
+ HSIO_TX_DWORD8[21:16]
+ <b>Default = 00h</b>
+ **/
+ UINT32 HsioTxDownscaleAmp : 6;
+
+ UINT32 RsvdBits1 : 18; ///< Reserved bits
+ UINT32 Rsvd1[1]; ///< Reserved bytes
+} PCH_USB30_PORT_CONFIG;
+
+#define PCH_XHCI_MODE_OFF 0
+#define PCH_XHCI_MODE_ON 1
+
+/**
+ These members describe some settings which are related to the SSIC ports.
+**/
+typedef struct {
+ /**
+ 0: Disable; <b>1: Enable</b> SSIC support.
+ **/
+ UINT32 Enable : 1;
+ UINT32 RsvdBits1 : 31;
+} PCH_XHCI_SSIC_PORT;
+/**
+ These members describe some settings which are related to the SSIC ports.
+**/
+typedef struct {
+ PCH_XHCI_SSIC_PORT SsicPort[PCH_XHCI_MAX_SSIC_PORT_COUNT];
+} PCH_SSIC_CONFIG;
+
+/**
+ The PCH_XDCI_CONFIG block describes the configurations
+ of the xDCI Usb Device controller.
+**/
+typedef struct {
+ /**
+ This member describes whether or not the xDCI controller should be enabled.
+ 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 Enable : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_XDCI_CONFIG;
+
+
+/**
+ This member describes the expected configuration of the PCH USB controllers,
+ Platform modules may need to refer Setup options, schematic, BIOS specification
+ to update this field.
+ The Usb20OverCurrentPins and Usb30OverCurrentPins field must be updated by referring
+ the schematic.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Added DelayPdoProgramming policy option.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This policy will disable XHCI compliance mode on all ports. Complicance Mode should be default enabled.
+ For the platform that support USB Type-C, it can disable Compliance Mode, and enable Compliance Mode when testing.
+ <b>0:Disable</b> , 1: Enable
+ **/
+ UINT32 DisableComplianceMode : 1;
+ /**
+ This policy option if set will move Port Disable Override register programming to ReadyToBoot event during DXE phase.
+ If not enabled it will program Port Disable Override register in PEI phase during PCH initialization
+ <b>0: Program in PEI phase </b>, 1: Program in DXE phase
+ **/
+ UINT32 DelayPdoProgramming : 1;
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+ /**
+ These members describe whether the USB2 Port N of PCH is enabled by platform modules.
+ Panel and Dock are used to describe the layout of USB port. Panel is only available for Desktop PCH.
+ Dock is only available for Mobile LPT.
+ **/
+ PCH_USB20_PORT_CONFIG PortUsb20[PCH_MAX_USB2_PORTS];
+ /**
+ These members describe whether the USB3 Port N of PCH is enabled by platform modules.
+ **/
+ PCH_USB30_PORT_CONFIG PortUsb30[PCH_MAX_USB3_PORTS];
+ /**
+ This member describes whether or not the xDCI controller should be enabled.
+ **/
+ PCH_XDCI_CONFIG XdciConfig;
+ /**
+ These members describe some settings which are related to the SSIC ports.
+ **/
+ PCH_SSIC_CONFIG SsicConfig;
+} PCH_USB_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _USB_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h
new file mode 100644
index 0000000000..610c1092fb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h
@@ -0,0 +1,38 @@
+/** @file
+ WatchDog policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _WATCH_DOG_CONFIG_H_
+#define _WATCH_DOG_CONFIG_H_
+
+#define WATCH_DOG_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gWatchDogPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This policy clears status bits and disable watchdog, then lock the
+ WDT registers.
+ while WDT is designed to be disabled and locked by Policy,
+ bios should not enable WDT by WDT PPI. In such case, bios shows the
+ warning message but not disable and lock WDT register to make sure
+ WDT event trigger correctly.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 DisableAndLock : 1; ///< <b>(Test)</b> Set 1 to clear WDT status, then disable and lock WDT registers. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 31;
+} PCH_WDT_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _WATCH_DOG_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h
new file mode 100644
index 0000000000..8b26020da2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h
@@ -0,0 +1,338 @@
+/** @file
+ Header file for GpioConfig structure used by GPIO library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GPIO_CONFIG_H_
+#define _GPIO_CONFIG_H_
+
+#pragma pack(push, 1)
+
+///
+/// For any GpioPad usage in code use GPIO_PAD type
+///
+typedef UINT32 GPIO_PAD;
+
+
+///
+/// For any GpioGroup usage in code use GPIO_GROUP type
+///
+typedef UINT32 GPIO_GROUP;
+
+/**
+ GPIO configuration structure used for pin programming.
+ Structure contains fields that can be used to configure pad.
+**/
+typedef struct {
+ /**
+ Pad Mode
+ Pad can be set as GPIO or one of its native functions.
+ When in native mode setting Direction (except Inversion), OutputState,
+ InterruptConfig, Host Software Pad Ownership and OutputStateLock are unnecessary.
+ Refer to definition of GPIO_PAD_MODE.
+ Refer to EDS for each native mode according to the pad.
+ **/
+ UINT32 PadMode : 5;
+ /**
+ Host Software Pad Ownership
+ Set pad to ACPI mode or GPIO Driver Mode.
+ Refer to definition of GPIO_HOSTSW_OWN.
+ **/
+ UINT32 HostSoftPadOwn : 2;
+ /**
+ GPIO Direction
+ Can choose between In, In with inversion, Out, both In and Out, both In with inversion and out or disabling both.
+ Refer to definition of GPIO_DIRECTION for supported settings.
+ **/
+ UINT32 Direction : 6;
+ /**
+ Output State
+ Set Pad output value.
+ Refer to definition of GPIO_OUTPUT_STATE for supported settings.
+ This setting takes place when output is enabled.
+ **/
+ UINT32 OutputState : 2;
+ /**
+ GPIO Interrupt Configuration
+ Set Pad to cause one of interrupts (IOxAPIC/SCI/SMI/NMI).
+ This setting is applicable only if GPIO is in GpioMode with input enabled.
+ Refer to definition of GPIO_INT_CONFIG for supported settings.
+ **/
+ UINT32 InterruptConfig : 9;
+ /**
+ GPIO Power Configuration.
+ This setting controls Pad Reset Configuration.
+ Refer to definition of GPIO_RESET_CONFIG for supported settings.
+ **/
+ UINT32 PowerConfig : 8;
+ /**
+ GPIO Electrical Configuration
+ This setting controls pads termination and voltage tolerance.
+ Refer to definition of GPIO_ELECTRICAL_CONFIG for supported settings.
+ **/
+ UINT32 ElectricalConfig : 9;
+ /**
+ GPIO Lock Configuration
+ This setting controls pads lock.
+ Refer to definition of GPIO_LOCK_CONFIG for supported settings.
+ **/
+ UINT32 LockConfig : 4;
+ /**
+ Additional GPIO configuration
+ Refer to definition of GPIO_OTHER_CONFIG for supported settings.
+ **/
+ UINT32 OtherSettings : 2;
+ UINT32 RsvdBits : 17; ///< Reserved bits for future extension
+} GPIO_CONFIG;
+
+
+typedef enum {
+ GpioHardwareDefault = 0x0 ///< Leave setting unmodified
+} GPIO_HARDWARE_DEFAULT;
+
+/**
+ GPIO Pad Mode
+ Refer to GPIO documentation on native functions available for certain pad.
+ If GPIO is set to one of NativeX modes then following settings are not applicable
+ and can be skipped:
+ - Interrupt related settings
+ - Host Software Ownership
+ - Output/Input enabling/disabling
+ - Output lock
+**/
+typedef enum {
+ GpioPadModeGpio = 0x1,
+ GpioPadModeNative1 = 0x3,
+ GpioPadModeNative2 = 0x5,
+ GpioPadModeNative3 = 0x7,
+ GpioPadModeNative4 = 0x9
+} GPIO_PAD_MODE;
+
+/**
+ Host Software Pad Ownership modes
+ This setting affects GPIO interrupt status registers. Depending on chosen ownership
+ some GPIO Interrupt status register get updated and other masked.
+ Please refer to EDS for HOSTSW_OWN register description.
+**/
+typedef enum {
+ GpioHostOwnDefault = 0x0, ///< Leave ownership value unmodified
+ /**
+ Set HOST ownership to ACPI.
+ Use this setting if pad is not going to be used by GPIO OS driver.
+ If GPIO is configured to generate SCI/SMI/NMI then this setting must be
+ used for interrupts to work
+ **/
+ GpioHostOwnAcpi = 0x1,
+ /**
+ Set HOST ownership to GPIO Driver mode.
+ Use this setting only if GPIO pad should be controlled by GPIO OS Driver.
+ GPIO OS Driver will be able to control the pad if appropriate entry in
+ ACPI exists (refer to ACPI specification for GpioIo and GpioInt descriptors)
+ **/
+ GpioHostOwnGpio = 0x3
+} GPIO_HOSTSW_OWN;
+
+///
+/// GPIO Direction
+///
+typedef enum {
+ GpioDirDefault = 0x0, ///< Leave pad direction setting unmodified
+ GpioDirInOut = (0x1 | (0x1 << 3)), ///< Set pad for both output and input
+ GpioDirInInvOut = (0x1 | (0x3 << 3)), ///< Set pad for both output and input with inversion
+ GpioDirIn = (0x3 | (0x1 << 3)), ///< Set pad for input only
+ GpioDirInInv = (0x3 | (0x3 << 3)), ///< Set pad for input with inversion
+ GpioDirOut = 0x5, ///< Set pad for output only
+ GpioDirNone = 0x7 ///< Disable both output and input
+} GPIO_DIRECTION;
+
+/**
+ GPIO Output State
+ This field is relevant only if output is enabled
+**/
+typedef enum {
+ GpioOutDefault = 0x0, ///< Leave output value unmodified
+ GpioOutLow = 0x1, ///< Set output to low
+ GpioOutHigh = 0x3 ///< Set output to high
+} GPIO_OUTPUT_STATE;
+
+/**
+ GPIO interrupt configuration
+ This setting is applicable only if pad is in GPIO mode and has input enabled.
+ GPIO_INT_CONFIG allows to choose which interrupt is generated (IOxAPIC/SCI/SMI/NMI)
+ and how it is triggered (edge or level). Refer to PADCFG_DW0 register description in
+ EDS for details on this settings.
+ Field from GpioIntNmi to GpioIntApic can be OR'ed with GpioIntLevel to GpioIntBothEdge
+ to describe an interrupt e.g. GpioIntApic | GpioIntLevel
+ If GPIO is set to cause an SCI then also GPI_GPE_EN is enabled for this pad.
+ If GPIO is set to cause an NMI then also GPI_NMI_EN is enabled for this pad.
+ Not all GPIO are capable of generating an SMI or NMI interrupt.
+ When routing GPIO to cause an IOxAPIC interrupt care must be taken, as this
+ interrupt cannot be shared and its IRQn number is not configurable.
+ Refer to EDS for GPIO pads IRQ numbers (PADCFG_DW1.IntSel)
+ If GPIO is under GPIO OS driver control and appropriate ACPI GpioInt descriptor
+ exist then use only trigger type setting (from GpioIntLevel to GpioIntBothEdge).
+ This type of GPIO Driver interrupt doesn't have any additional routing setting
+ required to be set by BIOS. Interrupt is handled by GPIO OS Driver.
+**/
+
+typedef enum {
+ GpioIntDefault = 0x0, ///< Leave value of interrupt routing unmodified
+ GpioIntDis = 0x1, ///< Disable IOxAPIC/SCI/SMI/NMI interrupt generation
+ GpioIntNmi = 0x3, ///< Enable NMI interrupt only
+ GpioIntSmi = 0x5, ///< Enable SMI interrupt only
+ GpioIntSci = 0x9, ///< Enable SCI interrupt only
+ GpioIntApic = 0x11, ///< Enable IOxAPIC interrupt only
+ GpioIntLevel = (0x1 << 5), ///< Set interrupt as level triggered
+ GpioIntEdge = (0x3 << 5), ///< Set interrupt as edge triggered (type of edge depends on input inversion)
+ GpioIntLvlEdgDis = (0x5 << 5), ///< Disable interrupt trigger
+ GpioIntBothEdge = (0x7 << 5) ///< Set interrupt as both edge triggered
+} GPIO_INT_CONFIG;
+
+#define B_GPIO_INT_CONFIG_INT_SOURCE_MASK 0x1F ///< Mask for GPIO_INT_CONFIG for interrupt source
+#define B_GPIO_INT_CONFIG_INT_TYPE_MASK 0xE0 ///< Mask for GPIO_INT_CONFIG for interrupt type
+
+/**
+ GPIO Power Configuration
+ GPIO_RESET_CONFIG allows to set GPIO Reset type (PADCFG_DW0.PadRstCfg) which will
+ be used to reset certain GPIO settings.
+ Refer to EDS for settings that are controllable by PadRstCfg.
+**/
+typedef enum {
+
+
+ GpioResetDefault = 0x00, ///< Leave value of pad reset unmodified
+ ///
+ /// @{
+ /// @deprecated settings. Maintained only for compatibility.
+ ///
+ GpioResetPwrGood = 0x09, ///< GPP: RSMRST; GPD: DSW_PWROK; (PadRstCfg = 00b = "Powergood")
+ GpioResetDeep = 0x0B, ///< Deep GPIO Reset (PadRstCfg = 01b = "Deep GPIO Reset")
+ GpioResetNormal = 0x0D, ///< GPIO Reset (PadRstCfg = 10b = "GPIO Reset" )
+ GpioResetResume = 0x0F, ///< GPP: Reserved; GPD: RSMRST; (PadRstCfg = 11b = "Resume Reset" )
+ ///
+ /// @}
+ ///
+ ///
+ /// New GPIO reset configuration options
+ ///
+ /**
+ Resume Reset (RSMRST)
+ GPP: PadRstCfg = 00b = "Powergood"
+ GPD: PadRstCfg = 11b = "Resume Reset"
+ Pad setting will reset on:
+ - DeepSx transition
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ **/
+ GpioResumeReset = 0x01,
+ /**
+ Host Deep Reset
+ PadRstCfg = 01b = "Deep GPIO Reset"
+ Pad settings will reset on:
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ **/
+ GpioHostDeepReset = 0x03,
+ /**
+ Platform Reset (PLTRST)
+ PadRstCfg = 10b = "GPIO Reset"
+ Pad settings will reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ - G3
+ **/
+ GpioPlatformReset = 0x05,
+ /**
+ Deep Sleep Well Reset (DSW_PWROK)
+ GPP: not applicable
+ GPD: PadRstCfg = 00b = "Powergood"
+ Pad settings will reset on:
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ **/
+ GpioDswReset = 0x07
+} GPIO_RESET_CONFIG;
+
+/**
+ GPIO Electrical Configuration
+ Set GPIO termination and Pad Tolerance (applicable only for some pads)
+ Field from GpioTermNone to GpioTermNative can be OR'ed with GpioTolerance1v8.
+**/
+typedef enum {
+ GpioTermDefault = 0x0, ///< Leave termination setting unmodified
+ GpioTermNone = 0x1, ///< none
+ GpioTermWpd5K = 0x5, ///< 5kOhm weak pull-down
+ GpioTermWpd20K = 0x9, ///< 20kOhm weak pull-down
+ GpioTermWpu1K = 0x13, ///< 1kOhm weak pull-up
+ GpioTermWpu2K = 0x17, ///< 2kOhm weak pull-up
+ GpioTermWpu5K = 0x15, ///< 5kOhm weak pull-up
+ GpioTermWpu20K = 0x19, ///< 20kOhm weak pull-up
+ GpioTermWpu1K2K = 0x1B, ///< 1kOhm & 2kOhm weak pull-up
+ /**
+ Native function controls pads termination
+ This setting is applicable only to some native modes.
+ Please check EDS to determine which native functionality
+ can control pads termination
+ **/
+ GpioTermNative = 0x1F,
+ GpioNoTolerance1v8 = (0x1 << 5), ///< Disable 1.8V pad tolerance
+ GpioTolerance1v8 = (0x3 << 5) ///< Enable 1.8V pad tolerance
+} GPIO_ELECTRICAL_CONFIG;
+
+#define B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK 0x1F ///< Mask for GPIO_ELECTRICAL_CONFIG for termination value
+#define B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK 0x60 ///< Mask for GPIO_ELECTRICAL_CONFIG for 1v8 tolerance setting
+
+/**
+ GPIO LockConfiguration
+ Set GPIO configuration lock and output state lock.
+ GpioLockPadConfig and GpioLockOutputState can be OR'ed.
+ Lock settings reset is in Powergood domain. Care must be taken when using this setting
+ as fields it locks may be reset by a different signal and can be controllable
+ by what is in GPIO_RESET_CONFIG (PADCFG_DW0.PadRstCfg). GPIO library provides
+ functions which allow to unlock a GPIO pad.
+**/
+typedef enum {
+ GpioLockDefault = 0x0, ///< Leave lock setting unmodified
+ GpioPadConfigLock = 0x3, ///< Lock Pad Configuration
+ GpioOutputStateLock = 0x5 ///< Lock GPIO pad output value
+} GPIO_LOCK_CONFIG;
+
+#define B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK 0x3 ///< Mask for GPIO_LOCK_CONFIG for Pad Configuration Lock
+#define B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK 0x5 ///< Mask for GPIO_LOCK_CONFIG for Pad Output Lock
+
+/**
+ Other GPIO Configuration
+ GPIO_OTHER_CONFIG is used for less often settings and for future extensions
+ Supported settings:
+ - RX raw override to '1' - allows to override input value to '1'
+ This setting is applicable only if in input mode (both in GPIO and native usage).
+ The override takes place at the internal pad state directly from buffer and before the RXINV.
+**/
+typedef enum {
+ GpioRxRaw1Default = 0x0, ///< Use default input override value
+ GpioRxRaw1Dis = 0x1, ///< Don't override input
+ GpioRxRaw1En = 0x3 ///< Override input to '1'
+} GPIO_OTHER_CONFIG;
+
+#define B_GPIO_OTHER_CONFIG_RXRAW_MASK 0x3 ///< Mask for GPIO_OTHER_CONFIG for RxRaw1 setting
+
+#pragma pack(pop)
+
+#endif //_GPIO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h
new file mode 100644
index 0000000000..5230656791
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h
@@ -0,0 +1,248 @@
+/** @file
+ GPIO pins for SKL-PCH-H,
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GPIO_PINS_SKL_H_H_
+#define _GPIO_PINS_SKL_H_H_
+///
+/// This header file should be used together with
+/// PCH GPIO lib in C and ASL. All defines used
+/// must match both ASL/C syntax
+///
+///
+/// SKL H GPIO Groups
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioGroup as argument
+///
+#define GPIO_SKL_H_GROUP_GPP_A 0x0100
+#define GPIO_SKL_H_GROUP_GPP_B 0x0101
+#define GPIO_SKL_H_GROUP_GPP_C 0x0102
+#define GPIO_SKL_H_GROUP_GPP_D 0x0103
+#define GPIO_SKL_H_GROUP_GPP_E 0x0104
+#define GPIO_SKL_H_GROUP_GPP_F 0x0105
+#define GPIO_SKL_H_GROUP_GPP_G 0x0106
+#define GPIO_SKL_H_GROUP_GPP_H 0x0107
+#define GPIO_SKL_H_GROUP_GPP_I 0x0108
+#define GPIO_SKL_H_GROUP_GPD 0x0109
+
+///
+/// SKL H GPIO pins
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioPad as argument. Encoding used here
+/// has all information required by library functions
+///
+#define GPIO_SKL_H_GPP_A0 0x01000000
+#define GPIO_SKL_H_GPP_A1 0x01000001
+#define GPIO_SKL_H_GPP_A2 0x01000002
+#define GPIO_SKL_H_GPP_A3 0x01000003
+#define GPIO_SKL_H_GPP_A4 0x01000004
+#define GPIO_SKL_H_GPP_A5 0x01000005
+#define GPIO_SKL_H_GPP_A6 0x01000006
+#define GPIO_SKL_H_GPP_A7 0x01000007
+#define GPIO_SKL_H_GPP_A8 0x01000008
+#define GPIO_SKL_H_GPP_A9 0x01000009
+#define GPIO_SKL_H_GPP_A10 0x0100000A
+#define GPIO_SKL_H_GPP_A11 0x0100000B
+#define GPIO_SKL_H_GPP_A12 0x0100000C
+#define GPIO_SKL_H_GPP_A13 0x0100000D
+#define GPIO_SKL_H_GPP_A14 0x0100000E
+#define GPIO_SKL_H_GPP_A15 0x0100000F
+#define GPIO_SKL_H_GPP_A16 0x01000010
+#define GPIO_SKL_H_GPP_A17 0x01000011
+#define GPIO_SKL_H_GPP_A18 0x01000012
+#define GPIO_SKL_H_GPP_A19 0x01000013
+#define GPIO_SKL_H_GPP_A20 0x01000014
+#define GPIO_SKL_H_GPP_A21 0x01000015
+#define GPIO_SKL_H_GPP_A22 0x01000016
+#define GPIO_SKL_H_GPP_A23 0x01000017
+#define GPIO_SKL_H_GPP_B0 0x01010000
+#define GPIO_SKL_H_GPP_B1 0x01010001
+#define GPIO_SKL_H_GPP_B2 0x01010002
+#define GPIO_SKL_H_GPP_B3 0x01010003
+#define GPIO_SKL_H_GPP_B4 0x01010004
+#define GPIO_SKL_H_GPP_B5 0x01010005
+#define GPIO_SKL_H_GPP_B6 0x01010006
+#define GPIO_SKL_H_GPP_B7 0x01010007
+#define GPIO_SKL_H_GPP_B8 0x01010008
+#define GPIO_SKL_H_GPP_B9 0x01010009
+#define GPIO_SKL_H_GPP_B10 0x0101000A
+#define GPIO_SKL_H_GPP_B11 0x0101000B
+#define GPIO_SKL_H_GPP_B12 0x0101000C
+#define GPIO_SKL_H_GPP_B13 0x0101000D
+#define GPIO_SKL_H_GPP_B14 0x0101000E
+#define GPIO_SKL_H_GPP_B15 0x0101000F
+#define GPIO_SKL_H_GPP_B16 0x01010010
+#define GPIO_SKL_H_GPP_B17 0x01010011
+#define GPIO_SKL_H_GPP_B18 0x01010012
+#define GPIO_SKL_H_GPP_B19 0x01010013
+#define GPIO_SKL_H_GPP_B20 0x01010014
+#define GPIO_SKL_H_GPP_B21 0x01010015
+#define GPIO_SKL_H_GPP_B22 0x01010016
+#define GPIO_SKL_H_GPP_B23 0x01010017
+#define GPIO_SKL_H_GPP_C0 0x01020000
+#define GPIO_SKL_H_GPP_C1 0x01020001
+#define GPIO_SKL_H_GPP_C2 0x01020002
+#define GPIO_SKL_H_GPP_C3 0x01020003
+#define GPIO_SKL_H_GPP_C4 0x01020004
+#define GPIO_SKL_H_GPP_C5 0x01020005
+#define GPIO_SKL_H_GPP_C6 0x01020006
+#define GPIO_SKL_H_GPP_C7 0x01020007
+#define GPIO_SKL_H_GPP_C8 0x01020008
+#define GPIO_SKL_H_GPP_C9 0x01020009
+#define GPIO_SKL_H_GPP_C10 0x0102000A
+#define GPIO_SKL_H_GPP_C11 0x0102000B
+#define GPIO_SKL_H_GPP_C12 0x0102000C
+#define GPIO_SKL_H_GPP_C13 0x0102000D
+#define GPIO_SKL_H_GPP_C14 0x0102000E
+#define GPIO_SKL_H_GPP_C15 0x0102000F
+#define GPIO_SKL_H_GPP_C16 0x01020010
+#define GPIO_SKL_H_GPP_C17 0x01020011
+#define GPIO_SKL_H_GPP_C18 0x01020012
+#define GPIO_SKL_H_GPP_C19 0x01020013
+#define GPIO_SKL_H_GPP_C20 0x01020014
+#define GPIO_SKL_H_GPP_C21 0x01020015
+#define GPIO_SKL_H_GPP_C22 0x01020016
+#define GPIO_SKL_H_GPP_C23 0x01020017
+#define GPIO_SKL_H_GPP_D0 0x01030000
+#define GPIO_SKL_H_GPP_D1 0x01030001
+#define GPIO_SKL_H_GPP_D2 0x01030002
+#define GPIO_SKL_H_GPP_D3 0x01030003
+#define GPIO_SKL_H_GPP_D4 0x01030004
+#define GPIO_SKL_H_GPP_D5 0x01030005
+#define GPIO_SKL_H_GPP_D6 0x01030006
+#define GPIO_SKL_H_GPP_D7 0x01030007
+#define GPIO_SKL_H_GPP_D8 0x01030008
+#define GPIO_SKL_H_GPP_D9 0x01030009
+#define GPIO_SKL_H_GPP_D10 0x0103000A
+#define GPIO_SKL_H_GPP_D11 0x0103000B
+#define GPIO_SKL_H_GPP_D12 0x0103000C
+#define GPIO_SKL_H_GPP_D13 0x0103000D
+#define GPIO_SKL_H_GPP_D14 0x0103000E
+#define GPIO_SKL_H_GPP_D15 0x0103000F
+#define GPIO_SKL_H_GPP_D16 0x01030010
+#define GPIO_SKL_H_GPP_D17 0x01030011
+#define GPIO_SKL_H_GPP_D18 0x01030012
+#define GPIO_SKL_H_GPP_D19 0x01030013
+#define GPIO_SKL_H_GPP_D20 0x01030014
+#define GPIO_SKL_H_GPP_D21 0x01030015
+#define GPIO_SKL_H_GPP_D22 0x01030016
+#define GPIO_SKL_H_GPP_D23 0x01030017
+#define GPIO_SKL_H_GPP_E0 0x01040000
+#define GPIO_SKL_H_GPP_E1 0x01040001
+#define GPIO_SKL_H_GPP_E2 0x01040002
+#define GPIO_SKL_H_GPP_E3 0x01040003
+#define GPIO_SKL_H_GPP_E4 0x01040004
+#define GPIO_SKL_H_GPP_E5 0x01040005
+#define GPIO_SKL_H_GPP_E6 0x01040006
+#define GPIO_SKL_H_GPP_E7 0x01040007
+#define GPIO_SKL_H_GPP_E8 0x01040008
+#define GPIO_SKL_H_GPP_E9 0x01040009
+#define GPIO_SKL_H_GPP_E10 0x0104000A
+#define GPIO_SKL_H_GPP_E11 0x0104000B
+#define GPIO_SKL_H_GPP_E12 0x0104000C
+#define GPIO_SKL_H_GPP_F0 0x01050000
+#define GPIO_SKL_H_GPP_F1 0x01050001
+#define GPIO_SKL_H_GPP_F2 0x01050002
+#define GPIO_SKL_H_GPP_F3 0x01050003
+#define GPIO_SKL_H_GPP_F4 0x01050004
+#define GPIO_SKL_H_GPP_F5 0x01050005
+#define GPIO_SKL_H_GPP_F6 0x01050006
+#define GPIO_SKL_H_GPP_F7 0x01050007
+#define GPIO_SKL_H_GPP_F8 0x01050008
+#define GPIO_SKL_H_GPP_F9 0x01050009
+#define GPIO_SKL_H_GPP_F10 0x0105000A
+#define GPIO_SKL_H_GPP_F11 0x0105000B
+#define GPIO_SKL_H_GPP_F12 0x0105000C
+#define GPIO_SKL_H_GPP_F13 0x0105000D
+#define GPIO_SKL_H_GPP_F14 0x0105000E
+#define GPIO_SKL_H_GPP_F15 0x0105000F
+#define GPIO_SKL_H_GPP_F16 0x01050010
+#define GPIO_SKL_H_GPP_F17 0x01050011
+#define GPIO_SKL_H_GPP_F18 0x01050012
+#define GPIO_SKL_H_GPP_F19 0x01050013
+#define GPIO_SKL_H_GPP_F20 0x01050014
+#define GPIO_SKL_H_GPP_F21 0x01050015
+#define GPIO_SKL_H_GPP_F22 0x01050016
+#define GPIO_SKL_H_GPP_F23 0x01050017
+#define GPIO_SKL_H_GPP_G0 0x01060000
+#define GPIO_SKL_H_GPP_G1 0x01060001
+#define GPIO_SKL_H_GPP_G2 0x01060002
+#define GPIO_SKL_H_GPP_G3 0x01060003
+#define GPIO_SKL_H_GPP_G4 0x01060004
+#define GPIO_SKL_H_GPP_G5 0x01060005
+#define GPIO_SKL_H_GPP_G6 0x01060006
+#define GPIO_SKL_H_GPP_G7 0x01060007
+#define GPIO_SKL_H_GPP_G8 0x01060008
+#define GPIO_SKL_H_GPP_G9 0x01060009
+#define GPIO_SKL_H_GPP_G10 0x0106000A
+#define GPIO_SKL_H_GPP_G11 0x0106000B
+#define GPIO_SKL_H_GPP_G12 0x0106000C
+#define GPIO_SKL_H_GPP_G13 0x0106000D
+#define GPIO_SKL_H_GPP_G14 0x0106000E
+#define GPIO_SKL_H_GPP_G15 0x0106000F
+#define GPIO_SKL_H_GPP_G16 0x01060010
+#define GPIO_SKL_H_GPP_G17 0x01060011
+#define GPIO_SKL_H_GPP_G18 0x01060012
+#define GPIO_SKL_H_GPP_G19 0x01060013
+#define GPIO_SKL_H_GPP_G20 0x01060014
+#define GPIO_SKL_H_GPP_G21 0x01060015
+#define GPIO_SKL_H_GPP_G22 0x01060016
+#define GPIO_SKL_H_GPP_G23 0x01060017
+#define GPIO_SKL_H_GPP_H0 0x01070000
+#define GPIO_SKL_H_GPP_H1 0x01070001
+#define GPIO_SKL_H_GPP_H2 0x01070002
+#define GPIO_SKL_H_GPP_H3 0x01070003
+#define GPIO_SKL_H_GPP_H4 0x01070004
+#define GPIO_SKL_H_GPP_H5 0x01070005
+#define GPIO_SKL_H_GPP_H6 0x01070006
+#define GPIO_SKL_H_GPP_H7 0x01070007
+#define GPIO_SKL_H_GPP_H8 0x01070008
+#define GPIO_SKL_H_GPP_H9 0x01070009
+#define GPIO_SKL_H_GPP_H10 0x0107000A
+#define GPIO_SKL_H_GPP_H11 0x0107000B
+#define GPIO_SKL_H_GPP_H12 0x0107000C
+#define GPIO_SKL_H_GPP_H13 0x0107000D
+#define GPIO_SKL_H_GPP_H14 0x0107000E
+#define GPIO_SKL_H_GPP_H15 0x0107000F
+#define GPIO_SKL_H_GPP_H16 0x01070010
+#define GPIO_SKL_H_GPP_H17 0x01070011
+#define GPIO_SKL_H_GPP_H18 0x01070012
+#define GPIO_SKL_H_GPP_H19 0x01070013
+#define GPIO_SKL_H_GPP_H20 0x01070014
+#define GPIO_SKL_H_GPP_H21 0x01070015
+#define GPIO_SKL_H_GPP_H22 0x01070016
+#define GPIO_SKL_H_GPP_H23 0x01070017
+#define GPIO_SKL_H_GPP_I0 0x01080000
+#define GPIO_SKL_H_GPP_I1 0x01080001
+#define GPIO_SKL_H_GPP_I2 0x01080002
+#define GPIO_SKL_H_GPP_I3 0x01080003
+#define GPIO_SKL_H_GPP_I4 0x01080004
+#define GPIO_SKL_H_GPP_I5 0x01080005
+#define GPIO_SKL_H_GPP_I6 0x01080006
+#define GPIO_SKL_H_GPP_I7 0x01080007
+#define GPIO_SKL_H_GPP_I8 0x01080008
+#define GPIO_SKL_H_GPP_I9 0x01080009
+#define GPIO_SKL_H_GPP_I10 0x0108000A
+#define GPIO_SKL_H_GPD0 0x01090000
+#define GPIO_SKL_H_GPD1 0x01090001
+#define GPIO_SKL_H_GPD2 0x01090002
+#define GPIO_SKL_H_GPD3 0x01090003
+#define GPIO_SKL_H_GPD4 0x01090004
+#define GPIO_SKL_H_GPD5 0x01090005
+#define GPIO_SKL_H_GPD6 0x01090006
+#define GPIO_SKL_H_GPD7 0x01090007
+#define GPIO_SKL_H_GPD8 0x01090008
+#define GPIO_SKL_H_GPD9 0x01090009
+#define GPIO_SKL_H_GPD10 0x0109000A
+#define GPIO_SKL_H_GPD11 0x0109000B
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h
new file mode 100644
index 0000000000..999b417011
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h
@@ -0,0 +1,207 @@
+/** @file
+ GPIO pins for SKL-PCH-LP,
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GPIO_PINS_SKL_LP_H_
+#define _GPIO_PINS_SKL_LP_H_
+///
+/// This header file should be used together with
+/// PCH GPIO lib in C and ASL. All defines used
+/// must match both ASL/C syntax
+///
+
+///
+/// SKL LP GPIO Groups
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioGroup as argument
+///
+#define GPIO_SKL_LP_GROUP_GPP_A 0x0200
+#define GPIO_SKL_LP_GROUP_GPP_B 0x0201
+#define GPIO_SKL_LP_GROUP_GPP_C 0x0202
+#define GPIO_SKL_LP_GROUP_GPP_D 0x0203
+#define GPIO_SKL_LP_GROUP_GPP_E 0x0204
+#define GPIO_SKL_LP_GROUP_GPP_F 0x0205
+#define GPIO_SKL_LP_GROUP_GPP_G 0x0206
+#define GPIO_SKL_LP_GROUP_GPD 0x0207
+
+///
+/// SKL LP GPIO pins
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioPad as argument. Encoding used here
+/// has all information required by library functions
+///
+#define GPIO_SKL_LP_GPP_A0 0x02000000
+#define GPIO_SKL_LP_GPP_A1 0x02000001
+#define GPIO_SKL_LP_GPP_A2 0x02000002
+#define GPIO_SKL_LP_GPP_A3 0x02000003
+#define GPIO_SKL_LP_GPP_A4 0x02000004
+#define GPIO_SKL_LP_GPP_A5 0x02000005
+#define GPIO_SKL_LP_GPP_A6 0x02000006
+#define GPIO_SKL_LP_GPP_A7 0x02000007
+#define GPIO_SKL_LP_GPP_A8 0x02000008
+#define GPIO_SKL_LP_GPP_A9 0x02000009
+#define GPIO_SKL_LP_GPP_A10 0x0200000A
+#define GPIO_SKL_LP_GPP_A11 0x0200000B
+#define GPIO_SKL_LP_GPP_A12 0x0200000C
+#define GPIO_SKL_LP_GPP_A13 0x0200000D
+#define GPIO_SKL_LP_GPP_A14 0x0200000E
+#define GPIO_SKL_LP_GPP_A15 0x0200000F
+#define GPIO_SKL_LP_GPP_A16 0x02000010
+#define GPIO_SKL_LP_GPP_A17 0x02000011
+#define GPIO_SKL_LP_GPP_A18 0x02000012
+#define GPIO_SKL_LP_GPP_A19 0x02000013
+#define GPIO_SKL_LP_GPP_A20 0x02000014
+#define GPIO_SKL_LP_GPP_A21 0x02000015
+#define GPIO_SKL_LP_GPP_A22 0x02000016
+#define GPIO_SKL_LP_GPP_A23 0x02000017
+#define GPIO_SKL_LP_GPP_B0 0x02010000
+#define GPIO_SKL_LP_GPP_B1 0x02010001
+#define GPIO_SKL_LP_GPP_B2 0x02010002
+#define GPIO_SKL_LP_GPP_B3 0x02010003
+#define GPIO_SKL_LP_GPP_B4 0x02010004
+#define GPIO_SKL_LP_GPP_B5 0x02010005
+#define GPIO_SKL_LP_GPP_B6 0x02010006
+#define GPIO_SKL_LP_GPP_B7 0x02010007
+#define GPIO_SKL_LP_GPP_B8 0x02010008
+#define GPIO_SKL_LP_GPP_B9 0x02010009
+#define GPIO_SKL_LP_GPP_B10 0x0201000A
+#define GPIO_SKL_LP_GPP_B11 0x0201000B
+#define GPIO_SKL_LP_GPP_B12 0x0201000C
+#define GPIO_SKL_LP_GPP_B13 0x0201000D
+#define GPIO_SKL_LP_GPP_B14 0x0201000E
+#define GPIO_SKL_LP_GPP_B15 0x0201000F
+#define GPIO_SKL_LP_GPP_B16 0x02010010
+#define GPIO_SKL_LP_GPP_B17 0x02010011
+#define GPIO_SKL_LP_GPP_B18 0x02010012
+#define GPIO_SKL_LP_GPP_B19 0x02010013
+#define GPIO_SKL_LP_GPP_B20 0x02010014
+#define GPIO_SKL_LP_GPP_B21 0x02010015
+#define GPIO_SKL_LP_GPP_B22 0x02010016
+#define GPIO_SKL_LP_GPP_B23 0x02010017
+#define GPIO_SKL_LP_GPP_C0 0x02020000
+#define GPIO_SKL_LP_GPP_C1 0x02020001
+#define GPIO_SKL_LP_GPP_C2 0x02020002
+#define GPIO_SKL_LP_GPP_C3 0x02020003
+#define GPIO_SKL_LP_GPP_C4 0x02020004
+#define GPIO_SKL_LP_GPP_C5 0x02020005
+#define GPIO_SKL_LP_GPP_C6 0x02020006
+#define GPIO_SKL_LP_GPP_C7 0x02020007
+#define GPIO_SKL_LP_GPP_C8 0x02020008
+#define GPIO_SKL_LP_GPP_C9 0x02020009
+#define GPIO_SKL_LP_GPP_C10 0x0202000A
+#define GPIO_SKL_LP_GPP_C11 0x0202000B
+#define GPIO_SKL_LP_GPP_C12 0x0202000C
+#define GPIO_SKL_LP_GPP_C13 0x0202000D
+#define GPIO_SKL_LP_GPP_C14 0x0202000E
+#define GPIO_SKL_LP_GPP_C15 0x0202000F
+#define GPIO_SKL_LP_GPP_C16 0x02020010
+#define GPIO_SKL_LP_GPP_C17 0x02020011
+#define GPIO_SKL_LP_GPP_C18 0x02020012
+#define GPIO_SKL_LP_GPP_C19 0x02020013
+#define GPIO_SKL_LP_GPP_C20 0x02020014
+#define GPIO_SKL_LP_GPP_C21 0x02020015
+#define GPIO_SKL_LP_GPP_C22 0x02020016
+#define GPIO_SKL_LP_GPP_C23 0x02020017
+#define GPIO_SKL_LP_GPP_D0 0x02030000
+#define GPIO_SKL_LP_GPP_D1 0x02030001
+#define GPIO_SKL_LP_GPP_D2 0x02030002
+#define GPIO_SKL_LP_GPP_D3 0x02030003
+#define GPIO_SKL_LP_GPP_D4 0x02030004
+#define GPIO_SKL_LP_GPP_D5 0x02030005
+#define GPIO_SKL_LP_GPP_D6 0x02030006
+#define GPIO_SKL_LP_GPP_D7 0x02030007
+#define GPIO_SKL_LP_GPP_D8 0x02030008
+#define GPIO_SKL_LP_GPP_D9 0x02030009
+#define GPIO_SKL_LP_GPP_D10 0x0203000A
+#define GPIO_SKL_LP_GPP_D11 0x0203000B
+#define GPIO_SKL_LP_GPP_D12 0x0203000C
+#define GPIO_SKL_LP_GPP_D13 0x0203000D
+#define GPIO_SKL_LP_GPP_D14 0x0203000E
+#define GPIO_SKL_LP_GPP_D15 0x0203000F
+#define GPIO_SKL_LP_GPP_D16 0x02030010
+#define GPIO_SKL_LP_GPP_D17 0x02030011
+#define GPIO_SKL_LP_GPP_D18 0x02030012
+#define GPIO_SKL_LP_GPP_D19 0x02030013
+#define GPIO_SKL_LP_GPP_D20 0x02030014
+#define GPIO_SKL_LP_GPP_D21 0x02030015
+#define GPIO_SKL_LP_GPP_D22 0x02030016
+#define GPIO_SKL_LP_GPP_D23 0x02030017
+#define GPIO_SKL_LP_GPP_E0 0x02040000
+#define GPIO_SKL_LP_GPP_E1 0x02040001
+#define GPIO_SKL_LP_GPP_E2 0x02040002
+#define GPIO_SKL_LP_GPP_E3 0x02040003
+#define GPIO_SKL_LP_GPP_E4 0x02040004
+#define GPIO_SKL_LP_GPP_E5 0x02040005
+#define GPIO_SKL_LP_GPP_E6 0x02040006
+#define GPIO_SKL_LP_GPP_E7 0x02040007
+#define GPIO_SKL_LP_GPP_E8 0x02040008
+#define GPIO_SKL_LP_GPP_E9 0x02040009
+#define GPIO_SKL_LP_GPP_E10 0x0204000A
+#define GPIO_SKL_LP_GPP_E11 0x0204000B
+#define GPIO_SKL_LP_GPP_E12 0x0204000C
+#define GPIO_SKL_LP_GPP_E13 0x0204000D
+#define GPIO_SKL_LP_GPP_E14 0x0204000E
+#define GPIO_SKL_LP_GPP_E15 0x0204000F
+#define GPIO_SKL_LP_GPP_E16 0x02040010
+#define GPIO_SKL_LP_GPP_E17 0x02040011
+#define GPIO_SKL_LP_GPP_E18 0x02040012
+#define GPIO_SKL_LP_GPP_E19 0x02040013
+#define GPIO_SKL_LP_GPP_E20 0x02040014
+#define GPIO_SKL_LP_GPP_E21 0x02040015
+#define GPIO_SKL_LP_GPP_E22 0x02040016
+#define GPIO_SKL_LP_GPP_E23 0x02040017
+#define GPIO_SKL_LP_GPP_F0 0x02050000
+#define GPIO_SKL_LP_GPP_F1 0x02050001
+#define GPIO_SKL_LP_GPP_F2 0x02050002
+#define GPIO_SKL_LP_GPP_F3 0x02050003
+#define GPIO_SKL_LP_GPP_F4 0x02050004
+#define GPIO_SKL_LP_GPP_F5 0x02050005
+#define GPIO_SKL_LP_GPP_F6 0x02050006
+#define GPIO_SKL_LP_GPP_F7 0x02050007
+#define GPIO_SKL_LP_GPP_F8 0x02050008
+#define GPIO_SKL_LP_GPP_F9 0x02050009
+#define GPIO_SKL_LP_GPP_F10 0x0205000A
+#define GPIO_SKL_LP_GPP_F11 0x0205000B
+#define GPIO_SKL_LP_GPP_F12 0x0205000C
+#define GPIO_SKL_LP_GPP_F13 0x0205000D
+#define GPIO_SKL_LP_GPP_F14 0x0205000E
+#define GPIO_SKL_LP_GPP_F15 0x0205000F
+#define GPIO_SKL_LP_GPP_F16 0x02050010
+#define GPIO_SKL_LP_GPP_F17 0x02050011
+#define GPIO_SKL_LP_GPP_F18 0x02050012
+#define GPIO_SKL_LP_GPP_F19 0x02050013
+#define GPIO_SKL_LP_GPP_F20 0x02050014
+#define GPIO_SKL_LP_GPP_F21 0x02050015
+#define GPIO_SKL_LP_GPP_F22 0x02050016
+#define GPIO_SKL_LP_GPP_F23 0x02050017
+#define GPIO_SKL_LP_GPP_G0 0x02060000
+#define GPIO_SKL_LP_GPP_G1 0x02060001
+#define GPIO_SKL_LP_GPP_G2 0x02060002
+#define GPIO_SKL_LP_GPP_G3 0x02060003
+#define GPIO_SKL_LP_GPP_G4 0x02060004
+#define GPIO_SKL_LP_GPP_G5 0x02060005
+#define GPIO_SKL_LP_GPP_G6 0x02060006
+#define GPIO_SKL_LP_GPP_G7 0x02060007
+#define GPIO_SKL_LP_GPD0 0x02070000
+#define GPIO_SKL_LP_GPD1 0x02070001
+#define GPIO_SKL_LP_GPD2 0x02070002
+#define GPIO_SKL_LP_GPD3 0x02070003
+#define GPIO_SKL_LP_GPD4 0x02070004
+#define GPIO_SKL_LP_GPD5 0x02070005
+#define GPIO_SKL_LP_GPD6 0x02070006
+#define GPIO_SKL_LP_GPD7 0x02070007
+#define GPIO_SKL_LP_GPD8 0x02070008
+#define GPIO_SKL_LP_GPD9 0x02070009
+#define GPIO_SKL_LP_GPD10 0x0207000A
+#define GPIO_SKL_LP_GPD11 0x0207000B
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h
new file mode 100644
index 0000000000..5362beeea3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h
@@ -0,0 +1,707 @@
+/** @file
+ Header file for GpioLib.
+ All function in this library is available for PEI, DXE, and SMM
+
+ @note: When GPIO pads are owned by ME Firmware, BIOS/host should not
+ attempt to access these GPIO Pads registers, registers value
+ returned in this case will be 0xFF.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GPIO_LIB_H_
+#define _GPIO_LIB_H_
+
+#include <GpioConfig.h>
+
+typedef struct {
+ GPIO_PAD GpioPad;
+ GPIO_CONFIG GpioConfig;
+} GPIO_INIT_CONFIG;
+/**
+ This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG structure.
+ Structure contains fields that can be used to configure each pad.
+ Pad not configured using GPIO_INIT_CONFIG will be left with hardware default values.
+ Separate fields could be set to hardware default if it does not matter, except
+ GpioPad and PadMode.
+ Some GpioPads are configured and switched to native mode by RC, those include:
+ SerialIo pins, ISH pins, ClkReq Pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ );
+
+//
+// Functions for setting/getting multiple GpioPad settings
+//
+
+/**
+ This procedure will read multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[out] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadConfig (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_CONFIG *GpioData
+ );
+
+/**
+ This procedure will configure multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_CONFIG *GpioData
+ );
+
+//
+// Functions for setting/getting single GpioPad properties
+//
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ );
+
+/**
+ This procedure will get GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] OutputVal GPIO Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetOutputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *OutputVal
+ );
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InputVal
+ );
+
+/**
+ This procedure will get GPIO IOxAPIC interrupt number
+
+ @param[in] GpioPad GPIO pad
+ @param[out] IrqNum IRQ number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadIoApicIrqNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *IrqNum
+ );
+
+/**
+ This procedure will configure GPIO input inversion
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIO input inversion
+ 0: No input inversion, 1: Invert input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ );
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InvertState
+ );
+
+/**
+ This procedure will set GPIO interrupt settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Level/Edge
+ use GPIO_INT_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadInterruptConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_INT_CONFIG Value
+ );
+
+/**
+ This procedure will set GPIO electrical settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of termination
+ use GPIO_ELECTRICAL_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadElectricalConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_ELECTRICAL_CONFIG Value
+ );
+
+/**
+ This procedure will set GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for Pad Reset Configuration
+ use GPIO_RESET_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG Value
+ );
+
+/**
+ This procedure will get GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Pad Reset Configuration
+ based on GPIO_RESET_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG *Value
+ );
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *HostSwRegVal
+ );
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 HostSwRegVal
+ );
+
+/**
+ This procedure will get Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadHostSwOwn Value of Host Software Pad Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadHostSwOwn
+ );
+
+/**
+ This procedure will set Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadHostSwOwn Pad Host Software Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadHostSwOwn
+ );
+
+///
+/// Possible values of Pad Ownership
+/// If Pad is not under Host ownership then GPIO registers
+/// are not accessible by host (e.g. BIOS) and reading them
+/// will return 0xFFs.
+///
+typedef enum {
+ GpioPadOwnHost = 0x0,
+ GpioPadOwnCsme = 0x1,
+ GpioPadOwnIsh = 0x2,
+} GPIO_PAD_OWN;
+
+/**
+ This procedure will get Gpio Pad Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadOwnVal Value of Pad Ownership
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadOwnership (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_OWN *PadOwnVal
+ );
+
+/**
+ This procedure will check state of Pad Config Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockRegVal Value of PadCfgLock register
+ Bit position - PadNumber
+ Bit value - 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockRegVal
+ );
+
+/**
+ This procedure will check state of Pad Config Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLock for selected pad
+ 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLock (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLock
+ );
+
+/**
+ This procedure will check state of Pad Config Tx Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
+ Bit position - PadNumber
+ Bit value - 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockTxRegVal
+ );
+
+/**
+ This procedure will check state of Pad Config Tx Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLockTx for selected pad
+ 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLockTx (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLockTx
+ );
+
+/**
+ This procedure will clear PadCfgLock for selected pads within one group.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnlock, 1: Unlock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlock
+ );
+
+/**
+ This procedure will clear PadCfgLock for selected pad.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioUnlockPadCfg (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will set PadCfgLock for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLock, 1: Lock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLock
+ );
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will clear PadCfgLockTx for selected pads within one group.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlockTx
+ );
+
+/**
+ This procedure will clear PadCfgLockTx for selected pad.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioUnlockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will set PadCfgLockTx for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLockTx Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLockTx
+ );
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get Group to GPE mapping.
+ Refer to BWG and EDS for GPIO GPE information.
+
+ @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupToGpeDwX (
+ IN GPIO_GROUP *GroupToGpeDw0,
+ IN GPIO_GROUP *GroupToGpeDw1,
+ IN GPIO_GROUP *GroupToGpeDw2
+ );
+
+/**
+ This procedure will set Group to GPE mapping.
+ Refer to BWG and EDS for GPIO GPE information.
+
+ @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGroupToGpeDwX (
+ IN GPIO_GROUP GroupToGpeDw0,
+ IN GPIO_GROUP GroupToGpeDw1,
+ IN GPIO_GROUP GroupToGpeDw2
+ );
+
+/**
+ This procedure will get GPE number for provided GpioPad.
+ PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
+ what results in the fact that certain Pad can cause different General Purpose Event. Only three
+ GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
+ event (GPE_111 for 2-tier).
+
+ 1-tier:
+ Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
+ to determine what _LXX ACPI method would be called on event on selected GPIO pad
+
+ 2-tier:
+ Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
+ will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
+ what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
+ registers for all GPIO groups not mapped to 1-tier GPE.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeNumber GPE number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpeNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *GpeNumber
+ );
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used by Smi Dispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ );
+
+/**
+ This procedure is used to disable all GPI SMI
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+GpioDisableAllGpiSmi (
+ VOID
+ );
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN GPIO_PAD GpioPad,
+ OUT UINTN *GpiNum
+ );
+
+/**
+ This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
+
+ @param[in] GpioPad GPIO pad
+
+ @retval Data 0 means 1-tier, 1 means 2-tier
+**/
+BOOLEAN
+GpioCheckFor2Tier (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used to clear GPE STS for a specified GpioPad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiGpeSts (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used to read GPE STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] Data GPE STS data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiGpeSts (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32* Data
+ );
+
+#endif // _GPIO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h
new file mode 100644
index 0000000000..5f2c57fd34
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h
@@ -0,0 +1,225 @@
+/** @file
+ Header file for GpioLib for native and Si specific usage.
+ All function in this library is available for PEI, DXE, and SMM,
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GPIO_NATIVE_LIB_H_
+#define _GPIO_NATIVE_LIB_H_
+
+#include <GpioConfig.h>
+
+/**
+ This procedure will get number of pads for certain GPIO group
+
+ @param[in] Group GPIO group number
+
+ @retval Value Pad number for group
+ If illegal group number then return 0
+**/
+UINT32
+GpioGetPadPerGroup (
+ IN GPIO_GROUP Group
+ );
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT8
+GpioGetNumberOfGroups (
+ VOID
+ );
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ );
+
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ );
+
+/**
+ This procedure will get group
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group
+**/
+GPIO_GROUP
+GpioGetGroupFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get group index (0 based) from GpioPad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup Gpio Group
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ );
+
+/**
+ This procedure will get pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ );
+
+/**
+ This procedure will return GpioPad from GroupIndex and PadNumber
+
+ @param[in] GroupIndex GPIO GroupIndex
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupIndexAndPadNumber (
+ IN UINT32 GroupIndex,
+ IN UINT32 PadNumber
+ );
+
+/**
+ This function sets SerialIo I2C controller pins into native mode
+
+ @param[in] SerialIoI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2cPinsIntoNativeMode (
+ IN UINT32 SerialIoI2cControllerNumber
+ );
+
+/**
+ This function sets SerialIo I2C controller pins tolerance
+
+ @param[in] SerialIoI2CControllerNumber I2C controller
+ @param[in] Pad1v8Tolerance TRUE: Enable 1v8 Pad tolerance
+ FALSE: Disable 1v8 Pad tolerance
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2CPinsTolerance (
+ IN UINT32 SerialIoI2CControllerNumber,
+ IN BOOLEAN Pad1v8Tolerance
+ );
+
+/**
+ This function sets SerialIo UART controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber UART controller
+ @param[in] HardwareFlowControl Hardware Flow control
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoUartPinsIntoNativeMode (
+ IN UINT32 SerialIoUartControllerNumber,
+ IN BOOLEAN HardwareFlowControl
+ );
+
+/**
+ This function sets SerialIo SPI controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber SPI controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoSpiPinsIntoNativeMode (
+ IN UINT32 SerialIoUartControllerNumber
+ );
+
+/**
+ This function checks if GPIO pin for SATA reset port is in GPIO MODE
+
+ @param[in] SataPort SATA port number
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsSataResetPortInGpioMode (
+ IN UINTN SataPort
+ );
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad
+ );
+
+#endif // _GPIO_NATIVE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h
new file mode 100644
index 0000000000..9f5da64dff
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h
@@ -0,0 +1,37 @@
+/** @file
+ Header file for OC WDT Library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _OC_WDT_LIB_H_
+#define _OC_WDT_LIB_H_
+
+/**
+ Check for unexpected reset.
+ If there was an unexpected reset, enforces WDT expiration.
+**/
+VOID
+OcWdtResetCheck (
+ VOID
+ );
+
+/**
+ This function install WDT PPI
+
+ @retval EFI_STATUS Results of the installation of the WDT PPI
+**/
+EFI_STATUS
+EFIAPI
+OcWdtInit (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
new file mode 100644
index 0000000000..30ad2713b5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
@@ -0,0 +1,345 @@
+/** @file
+ Header file for PchCycleDecodingLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_CYCLE_DECODING_LIB_H_
+#define _PCH_CYCLE_DECODING_LIB_H_
+
+/**
+ Set PCH ACPI base address.
+ The Address should not be 0 and should be 256 bytes alignment, and it is IO space, so must not exceed 0xFFFF.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [7] to diable ACPI base address first before changing base address.
+ 2. program PMC PCI offset 40h [15:2] to ACPI base address.
+ 3. set PMC PCI offset 44h [7] to enable ACPI base address.
+ 4. program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1].
+ 5. Program "ACPI Base Destination ID" PCR[DMI] + 27B8h[31:0] to [0x23A0].
+
+ @param[in] Address Address for ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseSet (
+ IN UINT16 Address
+ );
+
+/**
+ Get PCH ACPI base address.
+
+ @param[out] Address Address of ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseGet (
+ OUT UINT16 *Address
+ );
+
+/**
+ Set PCH PWRM base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [8] to diable PWRM base address first before changing PWRM base address.
+ 2. program PMC PCI offset 48h [31:16] to PM base address.
+ 3. set PMC PCI offset 44h [8] to enable PWRM base address.
+ 4. program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ 5. program "PM Base Control" PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0].
+
+ @param[in] Address Address for PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseSet (
+ IN UINT32 Address
+ );
+
+/**
+ Get PCH PWRM base address.
+
+ @param[out] Address Address of PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseGet (
+ OUT UINT32 *Address
+ );
+
+/**
+ Set PCH TCO base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 2. program Smbus PCI offset 50h [15:5] to TCO base address.
+ 3. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 4. program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [Smbus PCI offset 50h[15:5], 1].
+
+ @param[in] Address Address for TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseSet (
+ IN UINT16 Address
+ );
+
+/**
+ Get PCH TCO base address.
+
+ @param[out] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseGet (
+ OUT UINT16 *Address
+ );
+
+///
+/// structure of LPC general IO range register
+/// It contains base address, address mask, and enable status.
+///
+typedef struct {
+ UINT32 BaseAddr :16;
+ UINT32 Length :15;
+ UINT32 Enable : 1;
+} PCH_LPC_GEN_IO_RANGE;
+
+#define PCH_LPC_GEN_IO_RANGE_MAX 4
+///
+/// structure of LPC general IO range register list
+/// It lists all LPC general IO ran registers supported by PCH.
+///
+typedef struct {
+ PCH_LPC_GEN_IO_RANGE Range[PCH_LPC_GEN_IO_RANGE_MAX];
+} PCH_LPC_GEN_IO_RANGE_LIST;
+
+/**
+ Set PCH LPC generic IO range.
+ For generic IO range, the base address must align to 4 and less than 0xFFFF, and the length must be power of 2
+ and less than or equal to 256. Moreover, the address must be length aligned.
+ This function basically checks the address and length, which should not overlap with all other generic ranges.
+ If no more generic range register available, it returns out of resource error.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ The IO ranges below 0x100 have fixed target. The target might be ITSS,RTC,LPC,PMC or terminated inside P2SB
+ but all predefined and can't be changed. IO range below 0x100 will be skipped except 0x80-0x8F.
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ );
+
+/**
+ Get PCH LPC generic IO range list.
+ This function returns a list of base address, length, and enable for all LPC generic IO range regsiters.
+
+ @param[out] LpcGenIoRangeList Return all LPC generic IO range register status.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeGet (
+ OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList
+ );
+
+/**
+ Set PCH LPC memory range decoding.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program LPC/eSPI PCI 98h [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC/eSPI PCI 98h [31:16, 0] to [Address, 1].
+ 3. Program LPC/eSPI Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ );
+
+/**
+ Get PCH LPC memory range decoding address.
+
+ @param[out] Address Address of LPC memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeGet (
+ OUT UINT32 *Address
+ );
+
+/**
+ Set PCH BIOS range deocding.
+ This will check General Control and Status bit 10 (GCS.BBS) to identify SPI or LPC/eSPI and program BDE register accordingly.
+ Please check EDS for detail of BiosDecodeEnable bit definition.
+ bit 15: F8-FF Enable
+ bit 14: F0-F8 Enable
+ bit 13: E8-EF Enable
+ bit 12: E0-E8 Enable
+ bit 11: D8-DF Enable
+ bit 10: D0-D7 Enable
+ bit 9: C8-CF Enable
+ bit 8: C0-C7 Enable
+ bit 7: Legacy F Segment Enable
+ bit 6: Legacy E Segment Enable
+ bit 5: Reserved
+ bit 4: Reserved
+ bit 3: 70-7F Enable
+ bit 2: 60-6F Enable
+ bit 1: 50-5F Enable
+ bit 0: 40-4F Enable
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. if GCS.BBS is 0 (SPI), program SPI PCI offset D8h to BiosDecodeEnable.
+ if GCS.BBS is 1 (LPC/eSPi), program LPC/eSPI PCI offset D8h to BiosDecodeEnable.
+ 2. program LPC/eSPI/SPI BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC/eSPI or SPI PCI Offset D8h.
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+EFIAPI
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ );
+
+/**
+ Set PCH LPC IO decode ranges.
+ Program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC offset 80h.
+ Please check EDS for detail of Lpc IO decode ranges bit definition.
+ Bit 12: FDD range
+ Bit 9:8: LPT range
+ Bit 6:4: ComB range
+ Bit 2:0: ComA range
+
+ @param[in] LpcIoDecodeRanges Lpc IO decode ranges bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ );
+
+/**
+ Set PCH LPC IO enable decoding.
+ Setup LPC I/O Enables, PCR[DMI] + 2774h[15:0] to the same value program in LPC offset 82h.
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in LPC 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of Lpc IO decode ranges bit definition.
+
+ @param[in] LpcIoEnableDecoding Lpc IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ );
+
+/**
+ Set PCH IO port 80h cycle decoding to PCIE root port.
+ System BIOS is likely to do this very soon after reset before PCI bus enumeration, it must ensure that
+ the IO Base Address field (PCIe:1Ch[7:4]) contains a value greater than the IO Limit field (PCIe:1Ch[15:12])
+ before setting the IOSE bit. Otherwise the bridge will positively decode IO range 000h - FFFh by its default
+ IO range values.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ 2. Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'. Use byte write on GCS+1 and leave the BILD bit which is RWO.
+ 3. Program IOSE bit of PCIE:Reg04h[0] to '1' for PCH to send such IO cycles to PCIe bus for subtractive decoding.
+
+ @param[in] RpPhyNumber PCIE root port physical number.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+EFIAPI
+PchIoPort80DecodeSet (
+ IN UINTN RpPhyNumber
+ );
+
+/**
+ Get IO APIC regsiters base address.
+ It returns IO APIC INDEX, DATA, and EOI regsiter address once the parameter is not NULL.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] IoApicIndex Buffer of IO APIC INDEX regsiter address
+ @param[out] IoApicData Buffer of IO APIC DATA regsiter address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchIoApicBaseGet (
+ OPTIONAL OUT UINT32 *IoApicIndex,
+ OPTIONAL OUT UINT32 *IoApicData
+ );
+
+/**
+ Get HPET base address.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] HpetBase Buffer of HPET base address
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchHpetBaseGet (
+ OUT UINT32 *HpetBase
+ );
+
+#endif // _PCH_CYCLE_DECODING_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h
new file mode 100644
index 0000000000..2096645375
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h
@@ -0,0 +1,102 @@
+/** @file
+ Header file for PchEspiLib.
+ All function in this library is available for PEI, DXE, and SMM,
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_ESPI_LIB_H_
+#define _PCH_ESPI_LIB_H_
+
+/**
+ Is eSPI enabled in strap.
+
+ @retval TRUE Espi is enabled in strap
+ @retval FALSE Espi is disabled in strap
+**/
+BOOLEAN
+IsEspiEnabled (
+ VOID
+ );
+
+/**
+ Get configuration from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ OUT UINT32 *OutData
+ );
+
+/**
+ Set eSPI slave configuration
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[in] InData Configuration data to write
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF has been locked
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveSetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ IN UINT32 InData
+ );
+
+/**
+ Get status from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetStatus (
+ IN UINT32 SlaveId,
+ OUT UINT16 *OutData
+ );
+
+/**
+ eSPI slave in-band reset
+
+ @param[in] SlaveId eSPI slave ID
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveInBandReset (
+ IN UINT32 SlaveId
+ );
+
+#endif // _PEI_DXE_SMM_PCH_ESPI_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h
new file mode 100644
index 0000000000..5461286634
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h
@@ -0,0 +1,64 @@
+/** @file
+ Header file for PchGbeLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_GBE_LIB_H_
+#define _PCH_GBE_LIB_H_
+
+/**
+ Check whether GbE region is valid
+ Check SPI region directly since GBE might be disabled in SW.
+
+ @retval TRUE Gbe Region is valid
+ @retval FALSE Gbe Region is invalid
+**/
+BOOLEAN
+PchIsGbeRegionValid (
+ VOID
+ );
+
+/**
+ Returns GbE over PCIe port number based on a soft strap.
+
+ @return Root port number (1-based)
+ @retval 0 GbE over PCIe disabled
+**/
+UINT32
+PchGetGbePortNumber (
+ VOID
+ );
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbePresent (
+ VOID
+ );
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @deprecated Use PchIsGbePresent instead.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbeAvailable (
+ VOID
+ );
+
+#endif // _PCH_GBE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h
new file mode 100644
index 0000000000..65076800a9
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h
@@ -0,0 +1,114 @@
+/** @file
+ Header file for PchHsioLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_HSIO_LIB_H_
+#define _PCH_HSIO_LIB_H_
+
+/**
+ Represents HSIO lane
+**/
+typedef struct {
+ UINT8 Index; ///< Lane index
+ UINT8 Pid; ///< Sideband ID
+ UINT16 Base; ///< Sideband base address
+} HSIO_LANE;
+
+/**
+ The function returns the Port Id and lane owner for the specified lane
+
+ @param[in] PhyMode Phymode that needs to be checked
+ @param[out] Pid Common Lane End Point ID
+ @param[out] LaneOwner Lane Owner
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid lane number
+**/
+EFI_STATUS
+EFIAPI
+PchGetLaneInfo (
+ IN UINT32 LaneNum,
+ OUT UINT8 *PortId,
+ OUT UINT8 *LaneOwner
+ );
+
+/**
+ Get HSIO lane representation needed to perform any operation on the lane.
+
+ @param[in] LaneIndex Number of the HSIO lane
+ @param[out] HsioLane HSIO lane representation
+**/
+VOID
+HsioGetLane (
+ IN UINT8 LaneIndex,
+ OUT HSIO_LANE *HsioLane
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] PcieLaneIndex PCIE Root Port Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetPcieLaneNum (
+ UINT32 PcieLaneIndex,
+ UINT8 *LaneNum
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] SataLaneIndex Sata Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetSataLaneNum (
+ UINT32 SataLaneIndex,
+ UINT8 *LaneNum
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] Usb3LaneIndex USB3 Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetUsb3LaneNum (
+ UINT32 Usb3LaneIndex,
+ UINT8 *LaneNum
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[out] LaneNum GBE Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetGbeLaneNum (
+ UINT8 *LaneNum
+ );
+
+#endif // _PCH_HSIO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
new file mode 100644
index 0000000000..5902b92f18
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
@@ -0,0 +1,260 @@
+/** @file
+ Header file for PchInfoLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_INFO_LIB_H_
+#define _PCH_INFO_LIB_H_
+
+#include <PchAccess.h>
+
+typedef enum {
+ PchH = 1,
+ PchLp,
+ PchUnknownSeries
+} PCH_SERIES;
+
+typedef enum {
+ SklPch = 1,
+ KblPch,
+ PchUnknownGeneration
+} PCH_GENERATION;
+
+typedef enum {
+ RstUnsupported = 0,
+ RstPremium,
+ RstOptane,
+ RstMaxMode
+} RST_MODE;
+
+typedef enum {
+ PchMobileSku = 0,
+ PchDesktopSku,
+ PchServerSku,
+ PchUnknownSku,
+ PchMaxSku
+} PCH_SKU_TYPE;
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+EFIAPI
+PchStepping (
+ VOID
+ );
+
+/**
+ Determine if PCH is supported
+
+ @retval TRUE PCH is supported
+ @retval FALSE PCH is not supported
+**/
+BOOLEAN
+IsPchSupported (
+ VOID
+ );
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+EFIAPI
+GetPchSeries (
+ VOID
+ );
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+EFIAPI
+GetPchGeneration (
+ VOID
+ );
+
+/**
+ Get PCH SKU type
+
+ @retval PCH_SKU_TYPE Type of PCH SKU
+**/
+PCH_SKU_TYPE
+GetPchSkuType (
+ VOID
+ );
+
+/**
+ Get Lpc Did
+
+ @retval UINT16 Lpc Did
+**/
+UINT16
+EFIAPI
+GetLpcDid (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval PcieMaxRootPort Pch Maximum Pcie Root Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPciePortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Sata Port Number
+
+ @retval Pch Maximum Sata Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxSataPortNum (
+ VOID
+ );
+
+/**
+ Get Pch Usb Maximum Physical Port Number
+
+ @retval Pch Usb Maximum Physical Port Number
+**/
+UINT8
+EFIAPI
+GetPchUsbMaxPhysicalPortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb2PortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb3PortNum (
+ VOID
+ );
+
+/**
+ Get PCH stepping ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchStep Pch stepping
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ IN PCH_STEPPING PchStep,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ );
+
+/**
+ Get PCH series ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchSeries Pch series
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSeriesStr (
+ IN PCH_SERIES PchSeries,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ );
+
+/**
+ Get PCH Sku ASCII string
+ The return string is zero terminated.
+
+ @param [in] LpcDid LPC device id
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSkuStr (
+ IN UINT16 LpcDid,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ );
+
+/**
+ Get RST mode supported by the silicon
+
+ @retval RST_MODE RST mode supported by silicon
+**/
+RST_MODE
+EFIAPI
+GetSupportedRstMode (
+ VOID
+ );
+
+/**
+ Check if current SKU supports Optane mode
+
+ @retval TRUE This SKU supports Optane mode
+ @retval FALSE This SKU doesn't support Optane mode
+**/
+BOOLEAN
+EFIAPI
+IsOptaneModeSupported (
+ VOID
+ );
+
+/**
+ Check if current SKU supports RAID feature
+
+ @retval TRUE This SKU supports RAID
+ @retval FALSE This SKU doesn't support RAID
+**/
+BOOLEAN
+EFIAPI
+IsPchRaidSupported (
+ VOID
+ );
+#endif // _PCH_INFO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h
new file mode 100644
index 0000000000..8083ac4efd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h
@@ -0,0 +1,160 @@
+/** @file
+ Header file for PchP2sbLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_P2SB_LIB_H_
+#define _PCH_P2SB_LIB_H_
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet32 (
+ IN UINTN Offset,
+ OUT UINT32 *OutData
+ );
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet16 (
+ IN UINTN Offset,
+ OUT UINT16 *OutData
+ );
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 1byte.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet8 (
+ IN UINTN Offset,
+ OUT UINT8 *OutData
+ );
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet32 (
+ IN UINTN Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet16 (
+ IN UINTN Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ );
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 1bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet8 (
+ IN UINTN Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ );
+
+/**
+ Hide P2SB device.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchHideP2sb (
+ IN UINTN P2sbBase
+ );
+
+/**
+ Reveal P2SB device.
+ Also return the original P2SB status which is for Hidding P2SB or not after.
+ If OrgStatus is not NULL, then TRUE means P2SB is unhidden,
+ and FALSE means P2SB is hidden originally.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+ @param[out] OrgStatus Original P2SB hidding/unhidden status
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchRevealP2sb (
+ IN UINTN P2sbBase,
+ OUT BOOLEAN *OrgStatus
+ );
+
+#endif // _PCH_P2SB_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h
new file mode 100644
index 0000000000..d5084772dd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h
@@ -0,0 +1,110 @@
+/** @file
+ Header file for PchPcieRpLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PCIERP_LIB_H_
+#define _PCH_PCIERP_LIB_H_
+
+#define RST_PCIE_STORAGE_CR_1 0
+#define RST_PCIE_STORAGE_CR_2 1
+#define RST_PCIE_STORAGE_CR_3 2
+#define RST_PCIE_STORAGE_CR_INVALID 99
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 Pid;
+ UINT8 RpNumBase;
+} PCH_PCIE_CONTROLLER_INFO;
+
+/**
+ Get Pch Pcie Root Port Device and Function Number by Root Port physical Number
+
+ @param[in] RpNumber Root port physical number. (0-based)
+ @param[out] RpDev Return corresponding root port device number.
+ @param[out] RpFun Return corresponding root port function number.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ );
+
+/**
+ Get Root Port physical Number by Pch Pcie Root Port Device and Function Number
+
+ @param[in] RpDev Root port device number.
+ @param[in] RpFun Root port function number.
+ @param[out] RpNumber Return corresponding physical Root Port index (0-based)
+
+ @retval EFI_SUCCESS Physical root port is retrieved
+ @retval EFI_INVALID_PARAMETER RpDev and/or RpFun are invalid
+ @retval EFI_UNSUPPORTED Root port device and function is not assigned to any physical root port
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ );
+
+/**
+ Gets base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+ @return PCIe port base address.
+**/
+UINTN
+PchPcieBase (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Determines whether L0s is supported on current stepping.
+
+ @return TRUE if L0s is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieL0sSupported (
+ VOID
+ );
+
+/**
+ Some early SKL PCH steppings require Native ASPM to be disabled due to hardware issues:
+ - RxL0s exit causes recovery
+ - Disabling PCIe L0s capability disables L1
+ Use this function to determine affected steppings.
+
+ @return TRUE if Native ASPM is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieNativeAspmSupported (
+ VOID
+ );
+
+/**
+ Check the RST PCIe Storage Cycle Router number according to the root port number and PCH type
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT32 The RST PCIe Storage Cycle Router Number
+**/
+UINT32
+RstGetCycleRouterNumber (
+ IN UINT32 RootPortNum
+ );
+
+#endif // _PCH_PCIERP_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h
new file mode 100644
index 0000000000..149168993f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h
@@ -0,0 +1,196 @@
+/** @file
+ Header file for PchPcrLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PCR_LIB_H_
+#define _PCH_PCR_LIB_H_
+
+#include <PchAccess.h>
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT32 *OutData
+ );
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT16 *OutData
+ );
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT8 *OutData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 InData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 InData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 InData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ );
+
+#endif // _PCH_PCR_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h
new file mode 100644
index 0000000000..61a955802a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h
@@ -0,0 +1,50 @@
+/** @file
+ Header file for PchPmcLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PMC_LIB_H_
+#define _PCH_PMC_LIB_H_
+
+typedef enum {
+ WarmBoot = 1,
+ ColdBoot,
+ PwrFlr,
+ PwrFlrSys,
+ PwrFlrPch,
+ PchPmStatusMax
+} PCH_PM_STATUS;
+
+/**
+ Query PCH to determine the Pm Status
+
+ @param[in] PmStatus - The Pch Pm Status to be probed
+
+ @retval Status TRUE if Status querried is Valid or FALSE if otherwise
+**/
+BOOLEAN
+GetPchPmStatus (
+ PCH_PM_STATUS PmStatus
+ );
+
+/**
+ Funtion to check if Battery lost or CMOS cleared.
+
+ @reval TRUE Battery is always present.
+ @reval FALSE CMOS is cleared.
+**/
+BOOLEAN
+EFIAPI
+PchIsRtcBatteryGood (
+ VOID
+ );
+
+#endif // _PCH_PMC_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h
new file mode 100644
index 0000000000..f4e3659960
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h
@@ -0,0 +1,113 @@
+/** @file
+ Prototype of the PeiPchPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_PCH_POLICY_LIB_H_
+#define _PEI_PCH_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+
+/**
+ Print whole PCH_PREMEM_POLICY_PPI and serial out.
+
+ @param[in] SiPreMemPolicyPpi The RC PREMEM Policy PPI instance
+**/
+VOID
+EFIAPI
+PchPreMemPrintPolicyPpi (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+ );
+
+/**
+ Print whole SI_POLICY_PPI and serial out.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+PchPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ Get PCH PREMEM config block table total size.
+
+ @retval Size of PCH PREMEM config block table
+**/
+UINT16
+EFIAPI
+PchGetPreMemConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ Get PCH config block table total size.
+
+ @retval Size of PCH config block table
+**/
+UINT16
+EFIAPI
+PchGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ PchAddPreMemConfigBlocks add all PCH config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add PCH config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+PchAddPreMemConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+/**
+ PchAddConfigBlocks add all PCH config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add PCH config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+PchAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPreMemPolicy The pointer to SI PREMEM Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePreMemPolicy (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicy
+ );
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPolicyPpi The pointer to SI Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePolicy (
+ IN SI_POLICY_PPI *SiPolicy
+ );
+
+#endif // _PEI_PCH_POLICY_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h
new file mode 100644
index 0000000000..4a2924f8f6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h
@@ -0,0 +1,170 @@
+/** @file
+ Header file for PchPsfLib.
+ This is helper library of RC for PSF register programming.
+ It's not expected to be used in platform code.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PSF_LIB_H_
+#define _PCH_PSF_LIB_H_
+
+#include <Library/PchSerialIoLib.h>
+
+/**
+ This procedure will enable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfEnableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will disable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will disable SerailIO device at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will hide SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfHideSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will reveal SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfRevealSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will set BARx value for TraceHub ACPI device at PSF level
+
+ @param[in] BarNum BAR Number (0:BAR0, 1:BAR1)
+ @param[in] BarValue 32bit BAR value
+
+ @retval None
+**/
+VOID
+PsfSetTraceHubAcpiDeviceBarValue (
+ IN UINT8 BarNum,
+ IN UINT32 BarValue
+ );
+
+/**
+ This procedure will enable MSE for TraceHub ACPI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnableTraceHubAcpiDeviceMemorySpace (
+ VOID
+ );
+
+/**
+ Enable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfEnableHeciDevice (
+ IN UINT8 HeciDevice
+ );
+
+/**
+ Disable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfDisableHeciDevice (
+ IN UINT8 HeciDevice
+ );
+
+/**
+ Enable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableIderDevice (
+ VOID
+ );
+
+/**
+ Disable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableIderDevice (
+ VOID
+ );
+
+/**
+ Enable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableSolDevice (
+ VOID
+ );
+
+/**
+ Disable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableSolDevice (
+ VOID
+ );
+#endif // _PCH_PSF_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h
new file mode 100644
index 0000000000..448cd21f50
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h
@@ -0,0 +1,30 @@
+/** @file
+ Header file for PCH RESET Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_RESET_LIB_H_
+#define _PCH_RESET_LIB_H_
+
+
+/**
+ Initialize PCH Reset APIs
+
+ @retval EFI_SUCCESS APIs are installed successfully
+ @retval EFI_OUT_OF_RESOURCES Can't allocate pool
+**/
+EFI_STATUS
+EFIAPI
+PchInitializeReset (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h
new file mode 100644
index 0000000000..87d3318260
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h
@@ -0,0 +1,162 @@
+/** @file
+ Header file for PchSbiAccessLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SBI_ACCESS_LIB_H_
+#define _PCH_SBI_ACCESS_LIB_H_
+
+/**
+ PCH SBI Register structure
+**/
+typedef struct {
+ UINT32 SbiAddr;
+ UINT32 SbiExtAddr;
+ UINT32 SbiData;
+ UINT16 SbiStat;
+ UINT16 SbiRid;
+} PCH_SBI_REGISTER_STRUCT;
+
+/**
+ PCH SBI opcode definitions
+**/
+typedef enum {
+ MemoryRead = 0x0,
+ MemoryWrite = 0x1,
+ PciConfigRead = 0x4,
+ PciConfigWrite = 0x5,
+ PrivateControlRead = 0x6,
+ PrivateControlWrite = 0x7,
+ GpioLockUnlock = 0x13
+} PCH_SBI_OPCODE;
+
+/**
+ PCH SBI response status definitions
+**/
+typedef enum {
+ SBI_SUCCESSFUL = 0,
+ SBI_UNSUCCESSFUL = 1,
+ SBI_POWERDOWN = 2,
+ SBI_MIXED = 3,
+ SBI_INVALID_RESPONSE
+} PCH_SBI_RESPONSE;
+
+/**
+ Execute PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecution (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ );
+
+/**
+ Full function for executing PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in] Fbe First byte enable
+ @param[in] Bar Bar
+ @param[in] Fid Function ID
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecutionEx (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ );
+
+/**
+ This function saves all PCH SBI registers.
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in, out] PchSbiRegister Structure for saving the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterSave (
+ IN OUT PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ );
+
+/**
+ This function restores all PCH SBI registers
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in] PchSbiRegister Structure for restoring the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterRestore (
+ IN PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ );
+
+#endif // _PCH_SBI_ACCESS_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h
new file mode 100644
index 0000000000..4ee5a9713e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h
@@ -0,0 +1,219 @@
+/** @file
+ Header file for PCH Serial IO Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SERIAL_IO_LIB_H_
+#define _PCH_SERIAL_IO_LIB_H_
+
+typedef enum {
+ PchSerialIoIndexI2C0,
+ PchSerialIoIndexI2C1,
+ PchSerialIoIndexI2C2,
+ PchSerialIoIndexI2C3,
+ PchSerialIoIndexI2C4,
+ PchSerialIoIndexI2C5,
+ PchSerialIoIndexSpi0,
+ PchSerialIoIndexSpi1,
+ PchSerialIoIndexUart0,
+ PchSerialIoIndexUart1,
+ PchSerialIoIndexUart2,
+ PchSerialIoIndexMax
+} PCH_SERIAL_IO_CONTROLLER;
+
+typedef enum {
+ PchSerialIoDisabled,
+ PchSerialIoAcpi,
+ PchSerialIoPci,
+ PchSerialIoAcpiHidden,
+ PchSerialIoLegacyUart,
+ PchSerialIoSkipInit
+} PCH_SERIAL_IO_MODE;
+
+enum PCH_LP_SERIAL_IO_VOLTAGE_SEL {
+ PchSerialIoIs33V = 0,
+ PchSerialIoIs18V
+};
+enum PCH_LP_SERIAL_IO_CS_POLARITY {
+ PchSerialIoCsActiveLow = 0,
+ PchSerialIoCsActiveHigh = 1
+};
+enum PCH_LP_SERIAL_IO_HW_FLOW_CTRL {
+ PchSerialIoHwFlowCtrlDisabled = 0,
+ PchSerialIoHwFlowControlEnabled = 1
+};
+
+#define SERIALIO_HID_LENGTH 8 // including null terminator
+#define SERIALIO_UID_LENGTH 1
+#define SERIALIO_CID_LENGTH 1
+#define SERIALIO_TOTAL_ID_LENGTH SERIALIO_HID_LENGTH+SERIALIO_UID_LENGTH+SERIALIO_CID_LENGTH
+
+/**
+ Returns index of the last i2c controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval Index of I2C controller
+**/
+PCH_SERIAL_IO_CONTROLLER
+GetMaxI2cNumber (
+ VOID
+ );
+
+/**
+ Returns string with AcpiHID assigned to selected SerialIo controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval pointer to 8-byte string
+**/
+CHAR8*
+GetSerialIoAcpiHID (
+ IN PCH_SERIAL_IO_CONTROLLER Number
+ );
+
+/**
+ Checks if Device with given PciDeviceId is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] PciDevId Device ID
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE Yes it is a SerialIo controller
+ @retval FALSE No it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoPciDevId (
+ IN UINT16 PciDevId,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ );
+
+/**
+ Checks if Device with given AcpiHID string is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] AcpiHid String
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE yes it is a SerialIo controller
+ @retval FALSE no it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoAcpiHid (
+ IN CHAR8 *AcpiHid,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ );
+
+/**
+ Configures Serial IO Controller
+
+ @param[in] Controller
+ @param[in] DeviceMode
+
+ @retval None
+**/
+VOID
+ConfigureSerialIoController (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode
+ );
+
+/**
+ Initializes GPIO pins used by SerialIo I2C devices
+
+ @param[in] Controller
+ @param[in] DeviceMode
+ @param[in] I2cVoltage
+
+ @retval None
+**/
+VOID
+SerialIoI2cGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 I2cVoltage
+ );
+
+/**
+ Initializes GPIO pins used by SerialIo SPI devices
+
+ @param[in] Controller
+ @param[in] DeviceMode
+ @param[in] SpiCsPolarity
+
+ @retval None
+**/
+VOID
+SerialIoSpiGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 SpiCsPolarity
+ );
+
+/**
+ Initializes GPIO pins used by SerialIo devices
+
+ @param[in] Controller
+ @param[in] DeviceMode
+ @param[in] HardwareFlowControl
+
+ @retval None
+**/
+VOID
+SerialIoUartGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN BOOLEAN HardwareFlowControl
+ );
+
+/**
+ Finds PCI Device Number of SerialIo devices.
+ SerialIo devices' BDF is configurable
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo device number
+**/
+UINT8
+GetSerialIoDeviceNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ );
+
+/**
+ Finds PCI Function Number of SerialIo devices.
+ SerialIo devices' BDF is configurable
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo funciton number
+**/
+UINT8
+GetSerialIoFunctionNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ );
+
+/**
+ Finds BAR values of SerialIo devices.
+ SerialIo devices can be configured to not appear on PCI so traditional method of reading BAR might not work.
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+ @param[in] BarNumber 0=BAR0, 1=BAR1
+
+ @retval SerialIo Bar value
+**/
+UINTN
+FindSerialIoBar (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice,
+ IN UINT8 BarNumber
+ );
+
+
+#endif // _PEI_DXE_SMM_PCH_SERIAL_IO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h
new file mode 100644
index 0000000000..66c5945a7b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h
@@ -0,0 +1,98 @@
+/** @file
+ Header file for PCH Serial IO UART Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SERIAL_IO_UART_LIB_H_
+#define _PCH_SERIAL_IO_UART_LIB_H_
+
+/**
+ Initialize selected SerialIo UART.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[in] FifoEnable When TRUE, enables 64-byte FIFOs.
+ @param[in] BaudRate Baud rate.
+ @param[in] LineControl Data length, parity, stop bits.
+ @param[in] HardwareFlowControl Automated hardware flow control. If TRUE, hardware automatically checks CTS when sending data, and sets RTS when receiving data.
+**/
+VOID
+EFIAPI
+PchSerialIoUartInit (
+ IN UINT8 UartNumber,
+ IN BOOLEAN FifoEnable,
+ IN UINT32 BaudRate,
+ IN UINT8 LineControl,
+ IN BOOLEAN HardwareFlowControl
+ );
+
+
+/**
+ Write data to serial device.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[in] Buffer Point of data buffer which need to be writed.
+ @param[in] NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval Actual number of bytes writed to serial device.
+**/
+UINTN
+EFIAPI
+PchSerialIoUartOut (
+ IN UINT8 UartNumber,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+);
+
+/*
+ Read data from serial device and save the datas in buffer.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[out] Buffer Point of data buffer which need to be writed.
+ @param[in] NumberOfBytes Number of output bytes which are cached in Buffer.
+ @param[in] WaitUntilBufferFull When TRUE, function waits until whole buffer is filled. When FALSE, function returns as soon as no new characters are available.
+
+ @retval Actual number of bytes raed from serial device.
+
+**/
+UINTN
+EFIAPI
+PchSerialIoUartIn (
+ IN UINT8 UartNumber,
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes,
+ IN BOOLEAN WaitUntilBufferFull
+);
+
+/**
+ Polls a serial device to see if there is any data waiting to be read.
+ If there is data waiting to be read from the serial device, then TRUE is returned.
+ If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+
+ @retval TRUE Data is waiting to be read from the serial device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+PchSerialIoUartPoll (
+ IN UINT8 UartNumber
+ );
+
+
+#endif // _PEI_DXE_SMM_PCH_SERIAL_IO_UART_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h
new file mode 100644
index 0000000000..cdeeae5e6d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h
@@ -0,0 +1,28 @@
+/** @file
+ Header file for SMM Control PEI Library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SMM_CONTROL_LIB_H_
+#define _PCH_SMM_CONTROL_LIB_H_
+
+/**
+ This function install PEI SMM Control PPI
+
+ @retval EFI_STATUS Results of the installation of the SMM Control PPI
+**/
+EFI_STATUS
+EFIAPI
+PchSmmControlInit (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h
new file mode 100644
index 0000000000..f89e42a546
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h
@@ -0,0 +1,113 @@
+/** @file
+ Library that contains common parts of WdtPei and WdtDxe. Not a standalone module.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_WDT_COMMON_LIB_H_
+#define _PCH_WDT_COMMON_LIB_H_
+
+extern UINT8 mAllowExpectedReset;
+
+/**
+ Reads LPC bridge to get Watchdog Timer address
+
+
+ @retval UINT32 Watchdog's address
+**/
+UINT32
+WdtGetAddress (
+ VOID
+ );
+
+/**
+ Reloads WDT with new timeout value and starts it. Also sets Unexpected Reset bit, which
+ causes the next reset to be treated as watchdog expiration - unless AllowKnownReset()
+ function was called too.
+
+ @param[in] TimeoutValue Time in seconds before WDT times out. Supported range = 1 - 1024.
+
+ @retval EFI_SUCCESS if everything's OK
+ @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong
+**/
+EFI_STATUS
+EFIAPI
+WdtReloadAndStart (
+ IN UINT32 TimeoutValue
+ );
+
+/**
+ Disables WDT timer.
+
+
+**/
+VOID
+EFIAPI
+WdtDisable (
+ VOID
+ );
+
+/**
+ Returns WDT failure status.
+
+
+ @retval V_PCH_OC_WDT_CTL_STATUS_FAILURE If there was WDT expiration or unexpected reset
+ @retval V_PCH_OC_WDT_CTL_STATUS_OK Otherwise
+**/
+UINT8
+EFIAPI
+WdtCheckStatus (
+ VOID
+ );
+
+/**
+ Normally, each reboot performed while watchdog runs is considered a failure.
+ This function allows platform to perform expected reboots with WDT running,
+ without being interpreted as failures.
+ In DXE phase, it is enough to call this function any time before reset.
+ In PEI phase, between calling this function and performing reset, ReloadAndStart()
+ must not be called.
+
+
+**/
+VOID
+EFIAPI
+WdtAllowKnownReset (
+ VOID
+ );
+
+/**
+ Returns information if WDT coverage for the duration of BIOS execution
+ was requested by an OS application
+
+
+ @retval TRUE if WDT was requested
+ @retval FALSE if WDT was not requested
+**/
+UINT8
+EFIAPI
+IsWdtRequired (
+ VOID
+ );
+
+/**
+ Returns WDT enabled/disabled status.
+
+
+ @retval TRUE if WDT is enabled
+ @retval FALSE if WDT is disabled
+**/
+UINT8
+EFIAPI
+IsWdtEnabled (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h
new file mode 100644
index 0000000000..ba9586a7a2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h
@@ -0,0 +1,27 @@
+/** @file
+ Header file for SEC PCH Lib.
+ All function in this library is available for SEC
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SEC_PCH_LIB_H_
+#define _SEC_PCH_LIB_H_
+
+/**
+ This function do the PCH cycle decoding initialization.
+**/
+VOID
+EFIAPI
+EarlyCycleDecoding (
+ VOID
+ );
+
+#endif // _SEC_PCH_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h
new file mode 100644
index 0000000000..12dfaeb440
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h
@@ -0,0 +1,104 @@
+/** @file
+ The header file includes the common header files, defines
+ internal structure and functions used by SpiFlashCommonLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SPI_FLASH_COMMON_LIB_H__
+#define __SPI_FLASH_COMMON_LIB_H__
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define SECTOR_SIZE_4KB 0x1000 // Common 4kBytes sector size
+/**
+ Enable block protection on the Serial Flash device.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashLock (
+ VOID
+ );
+
+/**
+ Read NumBytes bytes of data from the address specified by
+ PAddress into Buffer.
+
+ @param[in] Address The starting physical address of the read.
+ @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
+ of bytes actually read.
+ @param[out] Buffer The destination data buffer for the read.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write NumBytes bytes of data from Buffer to the address specified by
+ PAddresss.
+
+ @param[in] Address The starting physical address of the write.
+ @param[in,out] NumBytes On input, the number of bytes to write. On output,
+ the actual number of bytes written.
+ @param[in] Buffer The source data buffer for the write.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase the block starting at Address.
+
+ @param[in] Address The starting physical address of the block to be erased.
+ This library assume that caller garantee that the PAddress
+ is at the starting address of this block.
+ @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
+ On output, the actual number of bytes erased.
+
+ @retval EFI_SUCCESS. Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+ IN UINTN Address,
+ IN UINTN *NumBytes
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h
new file mode 100644
index 0000000000..23cb544d67
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h
@@ -0,0 +1,49 @@
+/** @file
+ Header file for TraceHub Init Lib.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _TRACE_HUB_INIT_LIB_H_
+#define _TRACE_HUB_INIT_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <PchAccess.h>
+
+///
+/// The PCH_TRACE_HUB_ENABLE_MODE describes the desired TraceHub mode of operation
+///
+typedef enum {
+ TraceHubModeDisabled = 0, ///< Pch TraceHub Disabled
+ TraceHubModeHostDebugger = 2, ///< Pch TraceHub External Debugger Present
+ TraceHubModeMax
+} TRACE_HUB_ENABLE_MODE;
+
+/**
+ This function performs basic initialization for TraceHub
+ This routine will consume address range 0xFE0C0000 - 0xFE3FFFFF for BARs usage.
+ Although controller allows access to a 64bit address resource, PEI phase is a 32bit env,
+ addresses greater than 4G is not allowed by CPU address space.
+ So, the addresses must be limited to below 4G and UBARs should be set to 0.
+ If this routine is called by platform code, it is expected EnableMode is passed in as PchTraceHubModeDisabled,
+ relying on the Intel TH debugger to enable it through the "cratchpad0 bit [24]".
+ By this practice, it gives the validation team the capability to use single debug BIOS
+ to validate the early trace functionality and code path that enable/disable Intel TH using BIOS policy.
+
+ @param[in] EnableMode Trace Hub Enable Mode
+**/
+VOID
+TraceHubInitialize (
+ IN UINT8 EnableMode
+ );
+
+#endif // _TRACE_HUB_INIT_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h
new file mode 100644
index 0000000000..2c457e3a1e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h
@@ -0,0 +1,71 @@
+/** @file
+ Macros that simplify accessing PCH devices's PCI registers.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_ACCESS_H_
+#define _PCH_ACCESS_H_
+
+#include "PchLimits.h"
+#include "PchReservedResources.h"
+
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND 1
+#endif
+#ifndef STALL_ONE_SECOND
+#define STALL_ONE_SECOND 1000000
+#endif
+
+
+///
+/// The default PCH PCI bus number
+///
+#define DEFAULT_PCI_BUS_NUMBER_PCH 0
+
+//
+// Default Vendor ID and Subsystem ID
+//
+#define V_PCH_INTEL_VENDOR_ID 0x8086 ///< Default Intel PCH Vendor ID
+#define V_PCH_DEFAULT_SID 0x7270 ///< Default Intel PCH Subsystem ID
+#define V_PCH_DEFAULT_SVID_SID (V_INTEL_VENDOR_ID + (V_PCH_DEFAULT_SID << 16)) ///< Default INTEL PCH Vendor ID and Subsystem ID
+
+//
+// Include device register definitions
+//
+#include "PcieRegs.h"
+#include "Register/PchRegsPcr.h"
+#include "Register/PchRegsP2sb.h"
+#include "Register/PchRegsHda.h"
+#include "Register/PchRegsHsio.h"
+#include "Register/PchRegsLan.h"
+#include "Register/PchRegsLpc.h"
+#include "Register/PchRegsPmc.h"
+#include "Register/PchRegsPcie.h"
+#include "Register/PchRegsSata.h"
+#include "Register/PchRegsSmbus.h"
+#include "Register/PchRegsSpi.h"
+#include "Register/PchRegsThermal.h"
+#include "Register/PchRegsUsb.h"
+#include "Register/PchRegsGpio.h"
+#include "Register/PchRegsSerialIo.h"
+#include "Register/PchRegsCam.h"
+#include "Register/PchRegsTraceHub.h"
+#include "Register/PchRegsScs.h"
+#include "Register/PchRegsIsh.h"
+#include "Register/PchRegsDmi.h"
+#include "Register/PchRegsItss.h"
+#include "Register/PchRegsPsth.h"
+#include "Register/PchRegsPsf.h"
+#include "Register/PchRegsFia.h"
+#include "Register/PchRegsDci.h"
+
+#endif
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h
new file mode 100644
index 0000000000..905a4778ce
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h
@@ -0,0 +1,101 @@
+/** @file
+ Build time limits of PCH resources.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_LIMITS_H_
+#define _PCH_LIMITS_H_
+
+//
+// PCIe limits
+//
+#define PCH_MAX_PCIE_ROOT_PORTS KBL_PCH_H_PCIE_MAX_ROOT_PORTS
+#define SKL_PCH_H_PCIE_MAX_ROOT_PORTS 20
+#define KBL_PCH_H_PCIE_MAX_ROOT_PORTS 24
+#define PCH_LP_PCIE_MAX_ROOT_PORTS 12
+
+#define PCH_MAX_PCIE_CONTROLLERS KBL_PCH_H_PCIE_MAX_CONTROLLERS
+#define PCH_PCIE_CONTROLLER_PORTS 4u
+#define SKL_PCH_H_PCIE_MAX_CONTROLLERS (SKL_PCH_H_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+#define KBL_PCH_H_PCIE_MAX_CONTROLLERS (KBL_PCH_H_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+#define PCH_LP_PCIE_MAX_CONTROLLERS (PCH_LP_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+
+//
+// PCIe clocks limits
+//
+#define PCH_LP_PCIE_MAX_CLK_REQ 6
+#define PCH_H_PCIE_MAX_CLK_REQ 16
+
+//
+// RST PCIe Storage Cycle Router limits
+//
+#define PCH_MAX_RST_PCIE_STORAGE_CR 3
+
+//
+// SATA limits
+//
+#define PCH_MAX_SATA_PORTS PCH_H_AHCI_MAX_PORTS
+#define PCH_H_AHCI_MAX_PORTS 8 ///< Max number of sata ports in SKL PCH H
+#define PCH_LP_AHCI_MAX_PORTS 3 ///< Max number of sata ports in SKL PCH LP
+#define PCH_SATA_MAX_DEVICES_PER_PORT 1 ///< Max support device numner per port, Port Multiplier is not support.
+
+//
+// USB limits
+//
+#define PCH_MAX_USB2_PORTS PCH_H_XHCI_MAX_USB2_PORTS
+
+#define PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS 14 ///< Max Physical Connector XHCI, not counting virtual ports like USB-R.
+#define PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS 10 ///< Max Physical Connector XHCI, not counting virtual ports like USB-R.
+
+#define PCH_H_XHCI_MAX_USB2_PORTS 16 ///< 14 High Speed lanes + Including two ports reserved for USBr
+#define PCH_LP_XHCI_MAX_USB2_PORTS 12 ///< 10 High Speed lanes + Including two ports reserved for USBr
+
+#define PCH_MAX_USB3_PORTS PCH_H_XHCI_MAX_USB3_PORTS
+
+#define PCH_H_XHCI_MAX_USB3_PORTS 10 ///< 10 Super Speed lanes
+#define PCH_LP_XHCI_MAX_USB3_PORTS 6 ///< 6 Super Speed lanes
+
+#define PCH_XHCI_MAX_SSIC_PORT_COUNT 2 ///< 2 SSIC ports in SKL PCH-LP and SKL PCH-H
+
+//
+// SerialIo limits
+//
+#define PCH_SERIALIO_MAX_CONTROLLERS 11 ///< Number of SerialIo controllers, this includes I2C, SPI and UART
+#define PCH_SERIALIO_MAX_I2C_CONTROLLERS 6 ///< Number of SerialIo I2C controllers
+#define PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS 6 ///< Number of SerialIo I2C controllers for PCH-LP
+#define PCH_H_SERIALIO_MAX_I2C_CONTROLLERS 4 ///< Number of SerialIo I2C controllers for PCH-H
+#define PCH_SERIALIO_MAX_SPI_CONTROLLERS 2 ///< Number of SerialIo SPI controllers
+#define PCH_SERIALIO_MAX_UART_CONTROLLERS 3 ///< Number of SerialIo UART controllers
+
+//
+// ISH limits
+//
+#define PCH_ISH_MAX_GP_PINS 8
+#define PCH_ISH_MAX_UART_CONTROLLERS 2
+#define PCH_ISH_MAX_I2C_CONTROLLERS 3
+#define PCH_ISH_MAX_SPI_CONTROLLERS 1
+
+//
+// SCS limits
+//
+#define PCH_SCS_MAX_CONTROLLERS 3 ///< Number of Storage and Communication Subsystem controllers, this includes eMMC, SDIO, SDCARD
+
+//
+// Flash Protection Range Register
+//
+#define PCH_FLASH_PROTECTED_RANGES 5
+
+//
+// Number of eSPI slaves
+//
+#define PCH_ESPI_MAX_SLAVE_ID 2
+#endif // _PCH_LIMITS_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h
new file mode 100644
index 0000000000..664f66f296
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h
@@ -0,0 +1,54 @@
+/** @file
+
+ Definitions required to create PcieStorageInfoHob
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_PCIE_STORAGE_DETECT_HOB_
+#define _PCH_PCIE_STORAGE_DETECT_HOB_
+
+#include "PchLimits.h"
+
+#define PCIE_STORAGE_INFO_HOB_REVISION 1
+
+extern EFI_GUID gPchPcieStorageDetectHobGuid;
+
+typedef enum {
+ RstLinkWidthX1 = 1,
+ RstLinkWidthX2 = 2,
+ RstLinkWidthX4 = 4
+} RST_LINK_WIDTH;
+
+//
+// Stores information about connected PCIe storage devices used later by BIOS setup and RST remapping
+//
+#pragma pack(1)
+typedef struct {
+ UINT8 Revision;
+
+ //
+ // Stores the number of root ports occupied by a connected storage device, values from RST_LINK_WIDTH are supported
+ //
+ UINT8 PcieStorageLinkWidth[PCH_MAX_PCIE_ROOT_PORTS];
+
+ //
+ // Programming interface value for a given device, 0x02 - NVMe or RAID, 0x1 - AHCI storage, 0x0 - no device connected
+ //
+ UINT8 PcieStorageProgrammingInterface[PCH_MAX_PCIE_ROOT_PORTS];
+
+ //
+ // Stores information about cycle router number under a given PCIe controller
+ //
+ UINT8 RstCycleRouterMap[PCH_MAX_PCIE_CONTROLLERS];
+} PCIE_STORAGE_INFO_HOB;
+#pragma pack()
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h
new file mode 100644
index 0000000000..67b255fe97
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h
@@ -0,0 +1,54 @@
+/** @file
+ PCH configuration based on PCH policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_POLICY_COMMON_H_
+#define _PCH_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include "ConfigBlock/PcieRpConfig.h"
+#include "ConfigBlock/SataConfig.h"
+#include "ConfigBlock/IoApicConfig.h"
+#include "ConfigBlock/Cio2Config.h"
+#include "ConfigBlock/DmiConfig.h"
+#include "ConfigBlock/FlashProtectionConfig.h"
+#include "ConfigBlock/HdAudioConfig.h"
+#include "ConfigBlock/InterruptConfig.h"
+#include "ConfigBlock/IshConfig.h"
+#include "ConfigBlock/LanConfig.h"
+#include "ConfigBlock/LockDownConfig.h"
+#include "ConfigBlock/P2sbConfig.h"
+#include "ConfigBlock/PmConfig.h"
+#include "ConfigBlock/Port61Config.h"
+#include "ConfigBlock/ScsConfig.h"
+#include "ConfigBlock/SerialIoConfig.h"
+#include "ConfigBlock/SerialIrqConfig.h"
+#include "ConfigBlock/SpiConfig.h"
+#include "ConfigBlock/ThermalConfig.h"
+#include "ConfigBlock/UsbConfig.h"
+#include "ConfigBlock/EspiConfig.h"
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+
+
+#endif // _PCH_POLICY_COMMON_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
new file mode 100644
index 0000000000..8bd4c9b960
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
@@ -0,0 +1,65 @@
+/** @file
+ PCH configuration based on PCH policy
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PREMEM_POLICY_COMMON_H_
+#define _PCH_PREMEM_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include "ConfigBlock/DciConfig.h"
+#include "ConfigBlock/WatchDogConfig.h"
+#include "ConfigBlock/TraceHubConfig.h"
+#include "ConfigBlock/HpetConfig.h"
+#include "ConfigBlock/SmbusConfig.h"
+#include "ConfigBlock/LpcConfig.h"
+#include "ConfigBlock/HsioPcieConfig.h"
+#include "ConfigBlock/HsioSataConfig.h"
+#include "ConfigBlock/HsioConfig.h"
+
+#pragma pack (push,1)
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+
+/**
+ PCH Policy revision number
+ Any backwards compatible changes to this structure will result in an update in the revision number
+**/
+#define PCH_PREMEM_POLICY_REVISION 1
+
+/**
+ PCH Policy PPI\n
+ All PCH config block change history will be listed here\n\n
+
+ - <b>Revision 1</b>:
+ - Initial version.\n
+**/
+typedef struct _PCH_PREMEM_POLICY {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader;
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} PCH_PREMEM_POLICY;
+
+#pragma pack (pop)
+
+#endif // _PCH_PREMEM_POLICY_COMMON_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h
new file mode 100644
index 0000000000..e5de75c0e3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h
@@ -0,0 +1,62 @@
+/** @file
+ PCH preserved MMIO resource definitions.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PRESERVED_RESOURCES_H_
+#define _PCH_PRESERVED_RESOURCES_H_
+
+/**
+ PCH preserved MMIO range, 24 MB, from 0xFD000000 to 0xFE7FFFFF
+
+ Detailed recommended static allocation
+ +-------------------------------------------------------------------------+
+ | Size | Start | End | Usage |
+ | 16 MB | 0xFD000000 | 0xFDFFFFFF | SBREG |
+ | 64 KB | 0xFE000000 | 0xFE00FFFF | PMC MBAR |
+ | 4 KB | 0xFE010000 | 0xFE010FFF | SPI BAR0 |
+ | 88 KB | 0xFE020000 | 0xFE035FFF | SerialIo BAR in ACPI mode |
+ | 24 KB | 0xFE036000 | 0xFE03BFFF | Unused |
+ | 4 KB | 0xFE03C000 | 0xFE03CFFF | Thermal Device in ACPI mode |
+ | 524 KB | 0xFE03D000 | 0xFE0BFFFF | Unused |
+ | 256 KB | 0xFE0C0000 | 0xFE0FFFFF | TraceHub FW BAR |
+ | 1 MB | 0xFE100000 | 0xFE1FFFFF | TraceHub MTB BAR |
+ | 2 MB | 0xFE200000 | 0xFE3FFFFF | TraceHub SW BAR |
+ | 64 KB | 0xFE400000 | 0xFE40FFFF | CIO2 MMIO BAR in ACPI mode |
+ | 2 MB - 64KB | 0xFE410000 | 0xFE5FFFFF | Unused |
+ | 2 MB | 0xFE600000 | 0xFE7FFFFF | Temp address |
+ +-------------------------------------------------------------------------+
+**/
+#define PCH_PRESERVED_BASE_ADDRESS 0xFD000000 ///< Pch preserved MMIO base address
+#define PCH_PRESERVED_MMIO_SIZE 0x01800000 ///< 24MB
+#define PCH_PCR_BASE_ADDRESS 0xFD000000 ///< SBREG MMIO base address
+#define PCH_PCR_MMIO_SIZE 0x01000000 ///< 16MB
+#define PCH_PWRM_BASE_ADDRESS 0xFE000000 ///< PMC MBAR MMIO base address
+#define PCH_PWRM_MMIO_SIZE 0x00010000 ///< 64KB
+#define PCH_SPI_BASE_ADDRESS 0xFE010000 ///< SPI BAR0 MMIO base address
+#define PCH_SPI_MMIO_SIZE 0x00001000 ///< 4KB
+#define PCH_SERIAL_IO_BASE_ADDRESS 0xFE020000 ///< SerialIo MMIO base address
+#define PCH_SERIAL_IO_MMIO_SIZE 0x00016000 ///< 88KB
+#define PCH_THERMAL_BASE_ADDRESS 0xFE03C000 ///< Thermal Device in ACPI mode
+#define PCH_THERMAL_MMIO_SIZE 0x00001000 ///< 4KB
+#define PCH_TRACE_HUB_FW_BASE_ADDRESS 0xFE0C0000 ///< TraceHub FW MMIO base address
+#define PCH_TRACE_HUB_FW_MMIO_SIZE 0x00040000 ///< 256KB
+#define PCH_TRACE_HUB_MTB_BASE_ADDRESS 0xFE100000 ///< TraceHub MTB MMIO base address
+#define PCH_TRACE_HUB_MTB_MMIO_SIZE 0x00100000 ///< 1MB
+#define PCH_TRACE_HUB_SW_BASE_ADDRESS 0xFE200000 ///< TraceHub SW MMIO base address
+#define PCH_TRACE_HUB_SW_MMIO_SIZE 0x00200000 ///< 2MB
+#define PCH_CIO2_BASE_ADDRESS 0xFE400000 ///< CIO2 MMIO BAR in ACPI mode
+#define PCH_CIO2_MMIO_SIZE 0x00010000 ///< 64KB
+#define PCH_TEMP_BASE_ADDRESS 0xFE600000 ///< preserved temp address for misc usage
+#define PCH_TEMP_MMIO_SIZE 0x00200000 ///< 2MB
+
+#endif // _PCH_PRESERVED_RESOURCES_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
new file mode 100644
index 0000000000..c19677cccd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
@@ -0,0 +1,28 @@
+/** @file
+ PCH Reset Platform Specific definitions.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_RESET_PLATFORM_SPECIFIC_H_
+#define _PCH_RESET_PLATFORM_SPECIFIC_H_
+
+#define PCH_PLATFORM_SPECIFIC_RESET_STRING L"PCH_RESET"
+#define PCH_RESET_DATA_STRING_MAX_LENGTH (sizeof (PCH_PLATFORM_SPECIFIC_RESET_STRING) / sizeof (UINT16))
+
+extern EFI_GUID gPchGlobalResetGuid;
+
+typedef struct _RESET_DATA {
+ CHAR16 Description[PCH_RESET_DATA_STRING_MAX_LENGTH];
+ EFI_GUID Guid;
+} PCH_RESET_DATA;
+
+#endif // _PCH_RESET_PLATFORM_SPECIFIC_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h
new file mode 100644
index 0000000000..951dac00dc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h
@@ -0,0 +1,98 @@
+/** @file
+ PCH Reset PPI
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_RESET_PPI_H_
+#define _PCH_RESET_PPI_H_
+
+//
+// Extern the GUID for PPI users.
+//
+extern EFI_GUID gPchResetPpiGuid;
+extern EFI_GUID gPchResetCallbackPpiGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_RESET_PPI PCH_RESET_PPI;
+typedef struct _PCH_RESET_CALLBACK_PPI PCH_RESET_CALLBACK_PPI;
+
+//
+// Related Definitions
+//
+//
+// PCH Reset Types
+//
+typedef enum {
+ PchColdReset = 0,
+ PchWarmReset = 1,
+ PchShutdownReset = 2,
+ PchGlobalReset = 4,
+ PchResetTypeMax
+} PCH_RESET_TYPE;
+
+//
+// Member functions
+//
+/**
+ Execute Pch Reset from the host controller.
+
+ @param[in] This Pointer to the PCH_RESET_PPI instance.
+ @param[in] PchResetType Pch Reset Types which includes ColdReset, WarmReset,
+ ShutdownReset, GlobalReset
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER If ResetType is invalid.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET_PPI_API) (
+ IN PCH_RESET_PPI *This,
+ IN PCH_RESET_TYPE PchResetType
+ );
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] PchResetType Pch Reset Types which includes PowerCycle, Globalreset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback ppi. Or, none of
+ callback ppi is installed.
+ @retval Others Do not do any reset from PCH
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET_CALLBACK) (
+ IN PCH_RESET_TYPE PchResetType
+ );
+
+/**
+ Interface structure to execute Pch Reset from the host controller.
+**/
+struct _PCH_RESET_PPI {
+ PCH_RESET_PPI_API Reset;
+};
+
+/**
+ This ppi is used to execute PCH Reset from the host controller.
+ The PCH Reset protocol and PCH Reset PPI implement the Intel (R) PCH Reset Interface
+ for DXE and PEI environments, respectively. If other drivers need to run their
+ callback function right before issuing the reset, they can install PCH Reset
+ Callback Protocol/PPI before PCH Reset DXE/PEI driver to achieve that.
+**/
+struct _PCH_RESET_CALLBACK_PPI {
+ PCH_RESET_CALLBACK ResetCallback;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h
new file mode 100644
index 0000000000..cd98f3601c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h
@@ -0,0 +1,32 @@
+/** @file
+ This file defines the PCH SPI PPI which implements the
+ Intel(R) PCH SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SPI_PPI_H_
+#define _PCH_SPI_PPI_H_
+
+#include <Protocol/Spi.h>
+
+//
+// Extern the GUID for PPI users.
+//
+extern EFI_GUID gPchSpiPpiGuid;
+
+/**
+ Reuse the PCH_SPI_PROTOCOL definitions
+ This is possible becaues the PPI implementation does not rely on a PeiService pointer,
+ as it uses EDKII Glue Lib to do IO accesses
+**/
+typedef PCH_SPI_PROTOCOL PCH_SPI_PPI;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h
new file mode 100644
index 0000000000..b0bb6bccbd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h
@@ -0,0 +1,33 @@
+/** @file
+ Watchdog Timer PPI
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_WDT_H_
+#define _PEI_WDT_H_
+
+#include <Protocol/Wdt.h>
+//
+// MRC takes a lot of time to execute in debug mode
+//
+#define WDT_TIMEOUT_BETWEEN_PEI_DXE 60
+
+//
+// Extern the GUID for PPI users.
+//
+extern EFI_GUID gWdtPpiGuid;
+
+///
+/// Reuse WDT_PROTOCOL definition
+///
+typedef WDT_PROTOCOL WDT_PPI;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
new file mode 100644
index 0000000000..eb08a89f00
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
@@ -0,0 +1,141 @@
+/** @file
+ APIs of PCH ACPI SMI Dispatch Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchAcpiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH ACPI SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH ACPI SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_REGISTER) (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent ACPI SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH ACPI SMIs Dispatch Protocol
+ The PCH ACPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH ACPI related SMIs.
+ It contains SMI types of Pme, RtcAlarm, PmeB0, and Time overflow.
+**/
+struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH ACPI SMI DISPATCH PROTOCOL.
+ **/
+ PCH_ACPI_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ Pme
+ The event is triggered by hardware when the PME# signal goes active.
+ Additionally, the event is only triggered when SCI_EN is not set.
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER PmeRegister;
+ /**
+ PmeB0
+ The event is triggered PCH when any internal device with PCI Power Management
+ capabilities on bus 0 asserts the equivalent of the PME# signal.
+ Additionally, the event is only triggered when SCI_EN is not set.
+ The following are internal devices which can set this bit:
+ Intel HD Audio, Intel Management Engine "maskable" wake events, Integrated LAN,
+ SATA, xHCI, Intel SST
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER PmeB0Register;
+ /**
+ RtcAlarm
+ The event is triggered by hardware when the RTC generates an alarm
+ (assertion of the IRQ8# signal).
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER RtcAlarmRegister;
+ /**
+ TmrOverflow
+ The event is triggered any time bit 22 of the 24-bit timer goes high
+ (bits are numbered from 0 to 23).
+ This will occur every 2.3435 seconds. When the TMROF_EN bit (ABASE + 02h, bit 0) is set,
+ then the setting of the TMROF_STS bit will additionally generate an SMI#
+ Additionally, the event is only triggered when SCI_EN is not set.
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER TmrOverflowRegister;
+};
+
+/**
+ PCH ACPI SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_ACPI_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h
new file mode 100644
index 0000000000..ad1db3833a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h
@@ -0,0 +1,74 @@
+/** @file
+ PCH eMMC HS400 Tuning Protocol
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_EMMC_TUNING_PROTOCOL_H_
+#define _PCH_EMMC_TUNING_PROTOCOL_H_
+
+#define PCH_EMMC_TUNING_PROTOCOL_REVISION 2
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchEmmcTuningProtocolGuid;
+
+//
+// Forward declaration for PCH_EMMC_TUNING_PROTOCOL
+//
+typedef struct _PCH_EMMC_TUNING_PROTOCOL PCH_EMMC_TUNING_PROTOCOL;
+
+/**
+ This structure decribes the required Emmc info for HS400 tuning
+**/
+typedef struct {
+ EFI_HANDLE PartitionHandle; ///< eMMC partition handle for block read/write
+ EFI_LBA Lba; ///< Logical Block Address for HS400 Tuning block read/write
+ UINT32 RelativeDevAddress; ///< Device system address, dynamically assigned by the host during initialization.
+ UINT8 HS200BusWidth; ///< The value to be programmed for BUS_WIDTH[183] byte
+} EMMC_INFO;
+
+///
+/// This structure describes the return value after HS400 tuning
+///
+typedef struct {
+ UINT8 Hs400DataValid; ///< Set if Hs400 Tuning Data is valid after tuning
+ UINT8 Hs400RxStrobe1Dll; ///< Rx Strobe Delay Control - Rx Strobe Delay DLL 1 (HS400 Mode)
+ UINT8 Hs400TxDataDll; ///< Tx Data Delay Control 1 - Tx Data Delay (HS400 Mode)
+ UINT8 Hs400DriverStrength; ///< Hs400 Driver Strength
+} EMMC_TUNING_DATA;
+
+///
+/// EMMC HS400 TUNING INTERFACE
+///
+typedef EFI_STATUS (EFIAPI *EMMC_TUNE) (
+ IN PCH_EMMC_TUNING_PROTOCOL *This, ///< This pointer to PCH_EMMC_TUNING_PROTOCOL
+ /**
+ Revision parameter is used to verify the layout of EMMC_INFO and TUNINGDATA.
+ If the revision is not matched, means the revision of EMMC_INFO and TUNINGDATA is not matched.
+ And function will return immediately.
+ **/
+ IN UINT8 Revision,
+ IN EMMC_INFO *EmmcInfo, ///< Pointer to EMMC_INFO
+ OUT EMMC_TUNING_DATA *EmmcTuningData ///< Pointer to EMMC_TUNING_DATA
+);
+
+/**
+ PCH EMMC TUNING PROTOCOL INTERFACE
+ Platform code uses this protocol to configure Emmc Hs400 mode, by passing the EMMC_INFO information.
+ PCH will setting EMMC controller based on EMMC_INFO and return EMMC_TUNING_DATA to platform code.
+ Platform should keep values of EMMC_TUNING_DATA and uses to configure EMMC through policies, to
+ prevent from doing EMMC tuning every boot.
+**/
+struct _PCH_EMMC_TUNING_PROTOCOL {
+ EMMC_TUNE EmmcTune; ///< Emmc Hs400 Tuning Interface
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h
new file mode 100644
index 0000000000..7d7d3a5339
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h
@@ -0,0 +1,151 @@
+/** @file
+ SmmEspiDispatch Protocol
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_ESPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ESPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchEspiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH eSPI SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+**/
+typedef
+VOID
+(EFIAPI *PCH_ESPI_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Generic function to register different types of eSPI SMI types
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration successful
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+ @retval others Registration failed
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ESPI_SMI_REGISTER) (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ESPI_SMI_UNREGISTER) (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH eSPI SMIs Dispatch Protocol
+ The PCH ESPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH eSPI related SMIs.
+ It contains SMI types of BiosWr, EcAssertedVw, and eSPI Master asserted SMIs
+**/
+struct _PCH_ESPI_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Unregister eSPI SMI events
+ **/
+ PCH_ESPI_SMI_UNREGISTER UnRegister;
+ /**
+ Register a BIOS Write Protect event
+ **/
+ PCH_ESPI_SMI_REGISTER BiosWrProtectRegister;
+ /**
+ Register a BIOS Write Report event
+ **/
+ PCH_ESPI_SMI_REGISTER BiosWrReportRegister;
+ /**
+ Register a Peripheral Channel Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER PcErrNonFatalRegister;
+ /**
+ Register a Peripheral Channel Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER PcErrFatalRegister;
+ /**
+ Register a Virtual Wire Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER VwErrNonFatalRegister;
+ /**
+ Register a Virtual Wire Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER VwErrFatalRegister;
+ /**
+ Register a Flash Channel Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER FlashErrNonFatalRegister;
+ /**
+ Register a Flash Channel Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER FlashErrFatalRegister;
+ /**
+ Register a Link Error event
+ **/
+ PCH_ESPI_SMI_REGISTER LnkErrType1Register;
+ /**
+ Register a SMI handler for Espi slaver
+ This routine will also lock down ESPI_SMI_LOCK bit after registration and prevent
+ this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+ **/
+ PCH_ESPI_SMI_REGISTER EspiSlaveSmiRegister;
+};
+
+/**
+ PCH ESPI SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_ESPI_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h
new file mode 100644
index 0000000000..392733117b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h
@@ -0,0 +1,115 @@
+/** @file
+ APIs of PCH GPIO UNLOCK SMI Dispatch Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchGpioUnlockSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH GPIO UNLOCK SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for specific PCH GPIO UNLOCK SMI dispatch event.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_GPIO_UNLOCK_SMI_DISPATCH_REGISTER) (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent GPIO UNLOCK SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_GPIO_UNLOCK_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH GPIOUNLOCK SMI Dispatch Protocol
+ The PCH GPIO UNLOCK SMI DISPATCH PROTOCOL provides the ability to dispatch function for
+ PCH gpio unlock SMIs.
+**/
+struct _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH GPIO UNLOCK SMI DISPATCH PROTOCOL.
+ **/
+ PCH_GPIO_UNLOCK_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ GpioUnlock
+ The event is triggered if the GPIO registers lockdown logic is requesting an SMI#.
+ **/
+ PCH_GPIO_UNLOCK_SMI_DISPATCH_REGISTER Register;
+};
+
+/**
+ PCH GPIO UNLOCK SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_GPIO_UNLOCK_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h
new file mode 100644
index 0000000000..ff81aebddf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h
@@ -0,0 +1,57 @@
+/** @file
+ This file defines the PCH Info Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_INFO_H_
+#define _PCH_INFO_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchInfoProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_INFO_PROTOCOL PCH_INFO_PROTOCOL;
+
+/**
+ Protocol revision number
+ Any backwards compatible changes to this protocol will result in an update in the revision number
+ Major changes will require publication of a new protocol
+
+ Revision 1: Original version
+ Revision 2: Add PcieControllerCfg6 for KBL PCH-H
+**/
+#define PCH_INFO_PROTOCOL_REVISION 2
+
+/**
+ This protocol is used to provide the information of PCH controller.
+**/
+struct _PCH_INFO_PROTOCOL {
+ /**
+ This member specifies the revision of the PCH Info protocol. This field is used
+ to indicate backwards compatible changes to the protocol. Platform code that
+ consumes this protocol must read the correct revision value to correctly interpret
+ the content of the protocol fields.
+ **/
+ UINT8 Revision;
+
+ UINT8 PcieControllerCfg1;
+ UINT8 PcieControllerCfg2;
+ UINT8 PcieControllerCfg3;
+ UINT8 PcieControllerCfg4;
+ UINT8 PcieControllerCfg5;
+ UINT8 PcieControllerCfg6;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
new file mode 100644
index 0000000000..b80597ae9b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
@@ -0,0 +1,137 @@
+/** @file
+ APIs of PCH PCIE SMI Dispatch Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchPcieSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+typedef struct {
+ UINT8 RpIndex; ///< Root port index (0-based), 0: RP1, 1: RP2, n: RP(N+1)
+ UINT8 BusNum; ///< Root port pci bus number
+ UINT8 DevNum; ///< Root port pci device number
+ UINT8 FuncNum; ///< Root port pci function number
+} PCH_PCIE_SMI_RP_CONTEXT;
+
+/**
+ Callback function for an PCH PCIE RP SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+ @param[in] RpContext Pointer of PCH PCIE Root Port context.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH PCIERP SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[in] RpIndex Refer to PCH PCIE Root Port index.
+ 0: RP1, 1: RP2, n: RP(N+1)
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_REGISTER) (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent PCIE SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH PCIE SMIs Dispatch Protocol
+ The PCH PCIE SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH PCIE related SMIs.
+ It contains SMI types of HotPlug, LinkActive, and Link EQ.
+**/
+struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH PCIE SMI DISPATCH PROTOCOL.
+ **/
+ PCH_PCIE_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ PcieRpXHotPlug
+ The event is triggered when PCIE root port Hot-Plug Presence Detect.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER HotPlugRegister;
+ /**
+ PcieRpXLinkActive
+ The event is triggered when Hot-Plug Link Active State Changed.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER LinkActiveRegister;
+ /**
+ PcieRpXLinkEq
+ The event is triggered when Device Requests Software Link Equalization.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER LinkEqRegister;
+};
+
+/**
+ PCH PCIE SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_PCIE_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h
new file mode 100644
index 0000000000..b39543b36e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h
@@ -0,0 +1,121 @@
+/** @file
+ PCH Reset Protocol
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_RESET_PROTOCOL_H_
+#define _PCH_RESET_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchResetProtocolGuid;
+extern EFI_GUID gPchResetCallbackProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_RESET_PROTOCOL PCH_RESET_PROTOCOL;
+typedef struct _PCH_RESET_CALLBACK_PROTOCOL PCH_RESET_CALLBACK_PROTOCOL;
+
+//
+// Related Definitions
+//
+///
+/// PCH Reset Types
+///
+typedef enum {
+ PchColdReset = 0,
+ PchWarmReset = 1,
+ PchShutdownReset = 2,
+ PchGlobalReset = 4,
+ PchResetTypeMax
+} PCH_RESET_TYPE;
+
+//
+// Member functions
+//
+/**
+ Execute Pch Reset from the host controller.
+
+ @param[in] This Pointer to the PCH_RESET_PROTOCOL instance.
+ @param[in] ResetType UEFI defined reset type.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER If ResetType is invalid.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET) (
+ IN PCH_RESET_PROTOCOL *This,
+ IN EFI_RESET_TYPE ResetType,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ );
+
+/**
+ Retrieve PCH platform specific ResetData
+
+ @param[in] Guid PCH platform specific reset GUID.
+ @param[out] DataSize The size of ResetData in bytes.
+
+ @retval ResetData A platform specific reset that the exact type of
+ the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+ @retval NULL If Guid is not defined in PCH platform specific reset.
+**/
+typedef
+VOID *
+(EFIAPI *PCH_RESET_GET_RESET_DATA) (
+ IN EFI_GUID *Guid,
+ OUT UINTN *DataSize
+ );
+
+/**
+ Interface structure to execute Pch Reset from the host controller.
+**/
+struct _PCH_RESET_PROTOCOL {
+ PCH_RESET Reset;
+ PCH_RESET_GET_RESET_DATA GetResetData;
+};
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes PowerCycle, GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+ @retval Others Do not do any reset from PCH
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET_CALLBACK) (
+ IN PCH_RESET_TYPE ResetType
+ );
+
+/**
+ This protocol is used to execute PCH Reset from the host controller.
+ The PCH Reset protocol and PCH Reset PPI implement the Intel (R) PCH Reset Interface
+ for DXE and PEI environments, respectively. If other drivers need to run their
+ callback function right before issuing the reset, they can install PCH Reset
+ Callback Protocol/PPI before PCH Reset DXE/PEI driver to achieve that.
+**/
+struct _PCH_RESET_CALLBACK_PROTOCOL {
+ PCH_RESET_CALLBACK ResetCallback;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
new file mode 100644
index 0000000000..4f0508b238
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
@@ -0,0 +1,139 @@
+/** @file
+ APIs of PCH SMI Dispatch Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for specific PCH SMI dispatch event.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_REGISTER) (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH specific SMIs Dispatch Protocol
+ The PCH SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH misc SMIs.
+ It contains legacy SMIs and new PCH SMI types like:
+ SerialIrq, McSmi, Smbus, ...
+**/
+struct _PCH_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH SMI DISPATCH PROTOCOL.
+ **/
+ PCH_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ SerialIrq
+ The event is triggered while the SMI# was caused by the SERIRQ decoder.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SerialIrqRegister;
+ /**
+ McSmi
+ The event is triggered if there has been an access to the power management
+ microcontroller range (62h or 66h) and the Microcontroller Decode Enable #1 bit
+ in the LPC Bridge I/O Enables configuration register is 1 .
+ **/
+ PCH_SMI_DISPATCH_REGISTER McSmiRegister;
+ /**
+ SmBus
+ The event is triggered while the SMI# was caused by:
+ 1. The SMBus Slave receiving a message that an SMI# should be caused, or
+ 2. The SMBALERT# signal goes active and the SMB_SMI_EN bit is set and the
+ SMBALERT_DIS bit is cleared, or
+ 3. The SMBus Slave receiving a Host Notify message and the HOST_NOTIFY_INTREN and
+ the SMB_SMI_EN bits are set, or
+ 4. The PCH detecting the SMLINK_SLAVE_SMI command while in the S0 state.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SmbusRegister;
+ /**
+ SPI Asynchronous
+ When registered, the flash controller will generate an SMI when it blocks a BIOS write or erase.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SpiAsyncRegister;
+};
+
+/**
+ PCH SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
new file mode 100644
index 0000000000..5d0a4d34cf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
@@ -0,0 +1,72 @@
+/** @file
+ PCH SMM IO Trap Control Protocol
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SMM_IO_TRAP_CONTROL_H_
+#define _PCH_SMM_IO_TRAP_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmmIoTrapControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+ The Prototype of Pause and Resume IoTrap callback function.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_IO_TRAP_CONTROL_FUNCTION) (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for the SMM IO trap pause and resume protocol
+ This protocol provides the functions to runtime control the IoTrap SMI enabled/disable.
+ This applys the capability to the DispatchHandle which returned by IoTrap callback
+ registration, and the DispatchHandle which must be MergeDisable = TRUE and Address != 0.
+ Besides, when S3 resuem, it only restores the state of IoTrap callback registration.
+ The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL {
+ /**
+ This runtime pauses a registered IoTrap handler.
+ **/
+ PCH_SMM_IO_TRAP_CONTROL_FUNCTION Pause;
+ /**
+ This runtime resumes a registered IoTrap handler.
+ **/
+ PCH_SMM_IO_TRAP_CONTROL_FUNCTION Resume;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
new file mode 100644
index 0000000000..95c680e75c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
@@ -0,0 +1,72 @@
+/** @file
+ PCH SMM Periodic Timer Control Protocol
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+#define _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmmPeriodicTimerControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+ The Prototype of Pause and Resume SMM PERIODIC TIMER function.
+
+ @param[in] This Pointer to the PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION) (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for the SMM PERIODIC TIMER pause and resume protocol
+ This protocol provides the functions to runtime control the SM periodic timer enabled/disable.
+ This applies the capability to the DispatchHandle which returned by SMM periodic timer callback
+ registration.
+ Besides, when S3 resume, it only restores the state of callback registration.
+ The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL {
+ /**
+ This runtime pauses the registered periodic timer handler.
+ **/
+ PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION Pause;
+ /**
+ This runtime resumes the registered periodic timer handler.
+ **/
+ PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION Resume;
+};
+
+#endif // _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
new file mode 100644
index 0000000000..457cdb682c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
@@ -0,0 +1,157 @@
+/** @file
+ APIs of PCH TCO SMI Dispatch Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchTcoSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH TCO SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_TCO_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH TCO SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_REGISTER) (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent TCO SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH TCO SMIs Dispatch Protocol
+ The PCH TCO SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH TCO related SMIs.
+ It contains SMI types of Mch, TcoTimeout, OsTco, Nmi, IntruderDectect, and BiowWp.
+**/
+struct _PCH_TCO_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH TCO SMI DISPATCH PROTOCOL.
+ **/
+ PCH_TCO_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ Mch
+ The event is triggered when PCH received a DMI special cycle message using DMI indicating that
+ it wants to cause an SMI.
+ The software must read the processor to determine the reason for the SMI.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER MchRegister;
+ /**
+ TcoTimeout
+ The event is triggered by PCH to indicate that the SMI was caused by the TCO timer reaching 0.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER TcoTimeoutRegister;
+ /**
+ OsTco
+ The event is triggered when software caused an SMI# by writing to the TCO_DAT_IN register (TCOBASE + 02h).
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER OsTcoRegister;
+ /**
+ Nmi
+ The event is triggered by the PCH when an SMI# occurs because an event occurred that would otherwise have
+ caused an NMI (because NMI2SMI_EN is set)
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER NmiRegister;
+ /**
+ IntruderDectect
+ The event is triggered by PCH to indicate that an intrusion was detected.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER IntruderDetRegister;
+ /**
+ SpiBiosWp
+ This event is triggered when SMI# was caused by the TCO logic and
+ SPI flash controller asserted Synchronous SMI by BIOS lock enable set.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER SpiBiosWpRegister;
+ /**
+ LpcBiosWp
+ This event is triggered when SMI# was caused by the TCO logic and
+ LPC/eSPI BIOS lock enable set.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER LpcBiosWpRegister;
+ /**
+ NewCentury
+ This event is triggered when SMI# was caused by the TCO logic and
+ year of RTC date rolls over a century (99 to 00).
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER NewCenturyRegister;
+};
+
+/**
+ PCH TCO SMI dispatch revision number
+
+ Revision 1: Initial version
+ Revision 2: Add NEWCENTURY support
+**/
+#define PCH_TCO_SMI_DISPATCH_REVISION 2
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h
new file mode 100644
index 0000000000..4bc396132d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h
@@ -0,0 +1,126 @@
+/** @file
+ This file defines the PCH Serial GPIO Interface Protocol which implements the
+ Intel(R) Serial Data over GPIO Pin functionality Protocol Interface.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SERIAL_GPIO_PROTOCOL_H_
+#define _PCH_SERIAL_GPIO_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSerialGpioProtocolGuid;
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SERIAL_GPIO_PROTOCOL PCH_SERIAL_GPIO_PROTOCOL;
+
+#define SERIAL_GPIO_MAX_DATA_RATE 63
+#define WAIT_TIME 100000
+#define WAIT_PERIOD 10
+
+///
+/// Serial GPIO protocol data structures and definitions
+///
+typedef enum {
+ EnumSerialGpioDataByte,
+ EnumSerialGpioDataWord,
+ EnumSerialGpioDataUndefined,
+ EnumSerialGpioDataDword,
+ EnumSerialGpioDataMax
+} SERIAL_GPIO_DATA_WIDTH;
+
+//
+// Protocol member functions
+//
+/**
+ Register for one GPIO Pin that will be used as serial GPIO.
+ For SKL PCH only GPP_D_0-4 will have the capability to be used as serial GPIO.
+ The caller of this procedure need to be very clear of which GPIO should be used as serial GPIO,
+ it should not be input, native, conflict with other GPIO, or Index > 4 on the caller's platform.
+
+ @param[in] This Pointer to the PCH_SERIAL_GPIO_PROTOCOL instance.
+ @param[in] SerialGpioPad The GPIO pad number that will be used as serial GPIO for data sending.
+
+ @retval EFI_SUCCESS Opcode initialization on the SERIAL_GPIO host controller completed.
+ @retval EFI_ACCESS_DENIED The SERIAL_GPIO configuration interface is locked.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource available to initialize the device.
+ @retval EFI_DEVICE_ERROR Device error, operation failed.
+ @retval EFI_INVALID_PARAMETER SerialGpioPinIndex is out of range
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SERIAL_GPIO_REGISTER) (
+ IN PCH_SERIAL_GPIO_PROTOCOL * This,
+ IN UINT8 SerialGpioPad
+ );
+
+/**
+ Unregister for one GPIO Pin that has been used as serial GPIO, and recover the registers before
+ registering.
+
+ @param[in] This Pointer to the PCH_SERIAL_GPIO_PROTOCOL instance.
+ @param[in] SerialGpioPad The GPIO pad number that will be used as serial GPIO for data sending.
+
+ @retval EFI_SUCCESS Opcode initialization on the SERIAL_GPIO host controller completed.
+ @retval EFI_ACCESS_DENIED The SERIAL_GPIO configuration interface is locked.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource available to initialize the device.
+ @retval EFI_DEVICE_ERROR Device error, operation failed.
+ @retval EFI_INVALID_PARAMETER Invalid function parameters
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SERIAL_GPIO_UNREGISTER) (
+ IN PCH_SERIAL_GPIO_PROTOCOL * This,
+ IN UINT8 SerialGpioPad
+ );
+
+/**
+ Execute SERIAL_GPIO commands from the host controller.
+
+ @param[in] This Pointer to the PCH_SERIAL_GPIO_PROTOCOL instance.
+ @param[in] GpioPad GPIO pad number.
+ @param[in] DataRate The data rate for serial data transferring. 1 ~ SERIAL_GPIO_MAX_DATA_RATE; 1: 128ns intervals; ...; 8: 8*128 = 1024ns intervals, default value;...
+ @param[in] DataCountInByte Number of bytes of the data will be transmitted through the GPIO pin.
+ @param[in, out] Buffer Pointer to caller-allocated buffer containing the data sent through the GPIO pin.
+
+ @retval EFI_SUCCESS Execute succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, GPIO serial data sent failed.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SERIAL_GPIO_SEND_DATA) (
+ IN PCH_SERIAL_GPIO_PROTOCOL * This,
+ IN UINT8 GpioPad,
+ IN UINT8 DataRate,
+ IN UINTN DataCountInByte,
+ IN OUT UINT8 *Buffer
+ );
+/**
+ This Protocol allows a platform module to execute the IntelR Serial Data over
+ GPIO Pin functionality Protocol Interface.
+ The caller will first call the SerialGpioRegister() function to configure the GPIO
+ to be used. Then the caller will execute one or more calls to the SerialGpioSendData()
+ function to perform serial GPIO activities. Finally, the caller will use the
+ SerialGpioUnRegister() function to un-register and allow other consumers to utilize
+ the serial GPIO services.
+ If the serial GPIO capabilities are in use by another caller, the registration
+ function will return an error.
+**/
+struct _PCH_SERIAL_GPIO_PROTOCOL {
+ PCH_SERIAL_GPIO_REGISTER SerialGpioRegister; ///< Register for one GPIO pin that will be used as serial GPIO.
+ PCH_SERIAL_GPIO_SEND_DATA SerialGpioSendData; ///< Execute SERIAL_GPIO commands from the host controller.
+ PCH_SERIAL_GPIO_UNREGISTER SerialGpioUnRegister; ///< Un-register the current GPIO pin used for serial GPIO, and recovers the registers before registering.
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h
new file mode 100644
index 0000000000..e4ce8fb472
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h
@@ -0,0 +1,299 @@
+/** @file
+ This file defines the PCH SPI Protocol which implements the
+ Intel(R) PCH SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SPI_PROTOCOL_H_
+#define _PCH_SPI_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSpiProtocolGuid;
+extern EFI_GUID gPchSmmSpiProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+
+/**
+ Flash Region Type
+**/
+typedef enum {
+ FlashRegionDescriptor,
+ FlashRegionBios,
+ FlashRegionMe,
+ FlashRegionGbE,
+ FlashRegionPlatformData,
+ FlashRegionDer,
+ FlashRegionAll,
+ FlashRegionMax
+} FLASH_REGION_TYPE;
+
+//
+// Protocol member functions
+//
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_ERASE) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ );
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_SFDP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ );
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_JEDEC_ID) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ );
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE_STATUS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ );
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_STATUS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ );
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_GET_REGION_ADDRESS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ );
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_PCH_SOFTSTRAP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_CPU_SOFTSTRAP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ These protocols/PPI allows a platform module to perform SPI operations through the
+ Intel PCH SPI Host Controller Interface.
+**/
+struct _PCH_SPI_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ PCH_SPI_FLASH_READ FlashRead; ///< Read data from the flash part.
+ PCH_SPI_FLASH_WRITE FlashWrite; ///< Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+ PCH_SPI_FLASH_ERASE FlashErase; ///< Erase some area on the flash part.
+ PCH_SPI_FLASH_READ_SFDP FlashReadSfdp; ///< Read SFDP data from the flash part.
+ PCH_SPI_FLASH_READ_JEDEC_ID FlashReadJedecId; ///< Read Jedec Id from the flash part.
+ PCH_SPI_FLASH_WRITE_STATUS FlashWriteStatus; ///< Write the status register in the flash part.
+ PCH_SPI_FLASH_READ_STATUS FlashReadStatus; ///< Read status register in the flash part.
+ PCH_SPI_GET_REGION_ADDRESS GetRegionAddress; ///< Get the SPI region base and size
+ PCH_SPI_READ_PCH_SOFTSTRAP ReadPchSoftStrap; ///< Read PCH Soft Strap Values
+ PCH_SPI_READ_CPU_SOFTSTRAP ReadCpuSoftStrap; ///< Read CPU Soft Strap Values
+};
+
+/**
+ PCH SPI PPI/PROTOCOL revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_SPI_SERVICES_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h
new file mode 100644
index 0000000000..4a65e016e6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h
@@ -0,0 +1,118 @@
+/** @file
+ Watchdog Timer protocol
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _DXE_WDT_H_
+#define _DXE_WDT_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gWdtProtocolGuid;
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _WDT_PROTOCOL WDT_PROTOCOL;
+
+/**
+ Reloads WDT with new timeout value and starts it. Also sets Unexpected Reset bit, which
+ causes the next reset to be treated as watchdog expiration - unless AllowKnownReset()
+ function was called too.
+
+ @param[in] TimeoutValue Time in seconds before WDT times out. Supported range = 1 - 1024.
+
+ @retval EFI_SUCCESS if everything's OK
+ @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong
+**/
+typedef
+EFI_STATUS
+(EFIAPI *WDT_RELOAD_AND_START) (
+ UINT32 TimeoutValue
+ );
+
+/**
+ Returns WDT failure status.
+
+ @retval V_PCH_OC_WDT_CTL_STATUS_FAILURE If there was WDT expiration or unexpected reset
+ @retval V_PCH_OC_WDT_CTL_STATUS_OK Otherwise
+**/
+typedef
+UINT8
+(EFIAPI *WDT_CHECK_STATUS) (
+ VOID
+ );
+
+/**
+ Returns information if WDT coverage for the duration of BIOS execution
+ was requested by an OS application.
+
+ @retval TRUE if WDT was requested
+ @retval FALSE if WDT was not requested
+**/
+typedef
+UINT8
+(EFIAPI *IS_WDT_REQUIRED) (
+ VOID
+ );
+
+/**
+ Returns WDT enabled/disabled status.
+
+ @retval TRUE if WDT is enabled
+ @retval FALSE if WDT is disabled
+**/
+typedef
+UINT8
+(EFIAPI *IS_WDT_ENABLED) (
+ VOID
+ );
+
+/**
+ Disables WDT timer.
+**/
+typedef
+VOID
+(EFIAPI *WDT_DISABLE) (
+ VOID
+ );
+
+/**
+ Normally, each reboot performed while watchdog runs is considered a failure.
+ This function allows platform to perform expected reboots with WDT running,
+ without being interpreted as failures.
+ In DXE phase, it is enough to call this function any time before reset.
+ In PEI phase, between calling this function and performing reset, ReloadAndStart()
+ must not be called.
+**/
+typedef
+VOID
+(EFIAPI *WDT_ALLOW_KNOWN_RESET) (
+ VOID
+ );
+
+/**
+ These protocols and PPI allow a platform module to perform watch dog timer operations
+ through the Intel PCH LPC Host Controller Interface. The WDT protocol and WDT PPI
+ implement the Intel (R) Watch Dog timer for DXE, and PEI environments, respectively.
+ WDT_PROTOCOL referenced hereafter represents both WDT_PROTOCOL and WDT_PPI, as they
+ share the identical data structure.
+**/
+struct _WDT_PROTOCOL {
+ WDT_RELOAD_AND_START ReloadAndStart; ///< Reloads WDT with new timeout value and starts it.
+ WDT_CHECK_STATUS CheckStatus; ///< Returns WDT failure status.
+ WDT_DISABLE Disable; ///< Disables WDT timer.
+ WDT_ALLOW_KNOWN_RESET AllowKnownReset; ///< Perform expected reboots with WDT running, without being interpreted as failures.
+ IS_WDT_REQUIRED IsWdtRequired; ///< Returns information if WDT coverage for the duration of BIOS execution was requested by an OS application.
+ IS_WDT_ENABLED IsWdtEnabled; ///< Returns WDT enabled/disabled status.
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h
new file mode 100644
index 0000000000..c4be5c27e7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h
@@ -0,0 +1,151 @@
+/** @file
+ Register names for Camera block
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_CAM_H_
+#define _PCH_REGS_CAM_H_
+
+//
+// CIO2 Registers (D20:F3)
+//
+#define PCI_DEVICE_NUMBER_PCH_CIO2 20
+#define PCI_FUNCTION_NUMBER_PCH_CIO2 3
+#define V_PCH_CIO2_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_LP_CIO2_DEVICE_ID 0x9D32
+
+//
+// CIO2 PCI Configuration space definitions
+//
+#define R_PCH_CIO2_CIOLBA 0x10 // Camera IO Controller Lower Base Address
+#define R_PCH_CIO2_CIOUBA 0x14 // Camera IO Controller Upper Base Address
+#define B_PCH_CIO2_CFG_PMCSR_NSR BIT3 // No Software Reset
+#define R_PCH_CIO2_CFG_MID_MMC 0x90 // MSI Capability ID
+#define R_PCH_CIO2_CFG_MMLA 0x94 // MSI Message Lower Address
+#define R_PCH_CIO2_CFG_MMUA 0x98 // MSI Message Lower Address
+#define R_PCH_CIO2_CFG_MMD 0x9C // MSI Message Data
+#define R_PCH_CIO2_AFID 0xA0 // Advanced Features Capability Identifiers
+#define R_PCH_CIO2_AF_CMD_STS 0xA4 // Adavanced Features Command and Staus Register
+#define R_PCH_CIO2_CFG_PID_PC 0xD0 // Power Management Capability Identifiers
+#define R_PCH_CIO2_CFG_PMCSR 0xD4 // Power Management Control & Status
+#define V_PCH_CIO2_CFG_PMCSR_PS_D3HOT (BIT0 | BIT1)
+
+//
+// CAM_MMIO_CSI2
+//
+
+//
+// CAM_MMIO_PRI
+// Camera Pipe Host Controller's MMIO registers in Primary clock domain
+//
+#define R_PCH_CAM_MMIO_PRI_CIO2_CGC 0x1400 ///< CIO2 Clock Gating Control
+#define V_PCH_CAM_MMIO_PRI_CIO2_CGC_CLK_GATING_EN (0x00003D7E)
+#define V_PCH_CAM_MMIO_PRI_CIO2_CGC_CLK_GATING_DIS (0x05300000)
+#define R_PCH_CAM_MMIO_PRI_CIO2_D0I3C 0x1408 ///< CIO2 D0i3 Control Register
+#define B_PCH_CAM_MMIO_PRI_CIO2_D0I3C_I3 BIT2 ///< I3 (D0i3). SW sets this bit to 1 to move the IP into the D0i3 state. Writing this bit to 0 will return the IP to the fully active D0 state (D0i0)
+#define R_PCH_CAM_MMIO_PRI_PCE 0x1430 ///< PCE Power Control Enable Register
+#define B_PCH_CAM_MMIO_PRI_PCE_D3HE BIT2 ///< D3HE: D3-Hot Enable
+#define B_PCH_CAM_MMIO_PRI_PCE_I3E BIT1 ///< I3E: I3 Enable
+#define R_PCH_CAM_MMIO_PRI_CIO2_GPR0 0x1434 ///< CIO2 General Purpose register 0
+#define R_PCH_CAM_MMIO_PRI_CIO2_GPR1 0x1438 ///< CIO2 General Purpose register 1
+
+//
+// CAM_PVT CHC space defininitions
+// Private registers description for Camera Pipe Host Controller IP
+// MSG IOSF-SB Port 0xA1 (PID_CAM_CHC)
+//
+#define R_PCH_PCR_CAM_CHC_PVT_FUSVAL 0x00 ///< Fuse Value
+#define R_PCH_PCR_CAM_CHC_PVT_ECCLOG 0x04 ///< SRAM Error Count Log
+#define R_PCH_PCR_CAM_CHC_PVT_DBGCTL 0x08 ///< Debug Control
+#define R_PCH_PCR_CAM_CHC_PVT_FNCFG 0x0C ///< Lock bits
+#define B_PCH_PCR_CAM_CHC_PVT_FNCFG_MEM_LOCK BIT8 ///< lock all lockable field in MEM space
+#define B_PCH_PCR_CAM_CHC_PVT_FNCFG_BCLD BIT0 ///< lock all lockable fields in CFG space
+#define R_PCH_PCR_CAM_CHC_HDEVC 0x10 ///< Hidden Device register
+#define R_PCH_PCR_CAM_CHC_PVT_FUSE_DBG 0x14 ///< Hidden Device register
+
+//
+// fls space definitions
+// CSI2 host controller's FLIS registers
+// MSG IOSF-SB Port 0xAA (PID_CAM_FLS)
+//
+#define R_PCH_PCR_CAM_FLIS_CSI0_RXCNTRL 0x00
+#define R_PCH_PCR_CAM_FLIS_CSI0_RCCRCOMP 0x01
+#define R_PCH_PCR_CAM_FLIS_CSI0_BSCOMPARE 0x02
+#define R_PCH_PCR_CAM_FLIS_CSI1_RXCNTRL 0x03
+#define R_PCH_PCR_CAM_FLIS_CSI1_RCCRCOMP 0x04
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CFG1 0x05
+#define R_PCH_PCR_CAM_FLIS_CSI1_BSCOMPARE 0x06
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CFG2 0x07
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CFG3 0x08
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CFG2 0x09
+#define R_PCH_PCR_CAM_FLIS_CSI2_RXCNTRL 0x0A
+#define R_PCH_PCR_CAM_FLIS_CSI2_RCCRCOMP 0x0B
+#define R_PCH_PCR_CAM_FLIS_CSI2_BSCOMPARE 0x0C
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CMP_STAT 0x0D
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_ERR_REG 0x0E
+#define R_PCH_PCR_CAM_FLIS_CSI_CLKTRIM 0x0F
+#define R_PCH_PCR_CAM_FLIS_CSI3_RXCNTRL 0x10
+#define R_PCH_PCR_CAM_FLIS_CSI3_RCCRCOMP 0x11
+#define R_PCH_PCR_CAM_FLIS_CSI3_BSCOMPARE 0x12
+#define R_PCH_PCR_CAM_FLIS_CSI_CFG 0x13
+#define B_PCH_PCR_CAM_FLIS_CSI_CFG_ACIO_LB_EN BIT26
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CFG1 0x14
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CFG2 0x15
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CFG3 0x16
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CFG1 0x17
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CFG3 0x18
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_CFG1 0x19
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_CFG3 0x1A
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_ERR_REG 0x1B
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CMP_STAT 0x1C
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_ERR_REG 0x1D
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CMP_STAT 0x1E
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_ERR_REG 0x1F
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_CMP_STAT 0x20
+#define R_PCH_PCR_CAM_FLIS_CSI_RCOMPSTAT_REG 0x21
+#define R_PCH_PCR_CAM_FLIS_CSI_DLLCTL_REG 0x22
+#define R_PCH_PCR_CAM_FLIS_CSI_DATAEYE_REG 0x23
+#define R_PCH_PCR_CAM_FLIS_CSI_DATATRIM 0x24
+#define R_PCH_PCR_CAM_FLIS_CSI_CTLE 0x25
+#define R_PCH_PCR_CAM_FLIS_CSI0_DFT_CFG 0x26
+#define R_PCH_PCR_CAM_FLIS_CSI1_DFT_CFG 0x27
+#define R_PCH_PCR_CAM_FLIS_CSI2_DFT_CFG 0x28
+#define R_PCH_PCR_CAM_FLIS_CSI3_DFT_CFG 0x29
+#define R_PCH_PCR_CAM_FLIS_CSI_AFE_HS_CONTROL 0x2A
+#define R_PCH_PCR_CAM_FLIS_CSI_RCOMP_STATUS 0x2B
+#define R_PCH_PCR_CAM_FLIS_CSI_RCOMP_CONTROL 0x2C
+#define R_PCH_PCR_CAM_FLIS_CSI_DATAEYE1_REG 0x2D
+#define R_PCH_PCR_CAM_FLIS_CSI_ALL01 0x2E
+#define R_PCH_PCR_CAM_FLIS_CSI_DLLCTL1_REG 0x2F
+#define R_PCH_PCR_CAM_FLIS_CSI_DATATRIM1 0x30
+
+#endif
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h
new file mode 100644
index 0000000000..d38bd7f0c4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h
@@ -0,0 +1,50 @@
+/** @file
+ Register names for PCH DCI device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_DCI_H_
+#define _PCH_REGS_DCI_H_
+
+//
+// DCI PCR Registers
+//
+#define R_PCH_PCR_DCI_ECTRL 0x04 ///< DCI Control Register
+#define B_PCH_PCR_DCI_ECTRL_HDCIEN BIT4 ///< Host DCI enable
+#define B_PCH_PCR_DCI_ECTRL_HDCIEN_LOCK BIT0 ///< Host DCI Enable Lock
+#define R_PCH_PCR_DCI_ECKPWRCTL 0x08 ///< DCI Power Control
+#define R_PCH_PCR_DCI_PCE 0x30 ///< DCI Power Control Enable Register
+#define B_PCH_PCR_DCI_PCE_HAE BIT5 ///< Hardware Autonomous Enable
+#define B_PCH_PCR_DCI_PCE_D3HE BIT2 ///< D3-Hot Enable
+#define B_PCH_PCR_DCI_PCE_I3E BIT1 ///< I3 Enable
+#define B_PCH_PCR_DCI_PCE_PMCRE BIT0 ///< PMC Request Enable
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h
new file mode 100644
index 0000000000..942aeda324
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h
@@ -0,0 +1,214 @@
+/** @file
+ Register names for DMI and OP-DMI
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_DMI_H_
+#define _PCH_REGS_DMI_H_
+
+//
+// DMI Chipset Configuration Registers (PID:DMI)
+//
+
+//
+// VC Configuration (Common)
+//
+#define R_PCH_PCR_DMI_V0CTL 0x2014 ///< Virtual channel 0 resource control
+#define B_PCH_PCR_DMI_V0CTL_EN BIT31
+#define B_PCH_PCR_DMI_V0CTL_ID (7 << 24) ///< Bit[26:24]
+#define N_PCH_PCR_DMI_V0CTL_ID 24
+#define V_PCH_PCR_DMI_V0CTL_ETVM_MASK 0xFC00
+#define V_PCH_PCR_DMI_V0CTL_TVM_MASK 0x7E
+#define R_PCH_PCR_DMI_V0STS 0x201A ///< Virtual channel 0 status
+#define B_PCH_PCR_DMI_V0STS_NP BIT1
+#define R_PCH_PCR_DMI_V1CTL 0x2020 ///< Virtual channel 1 resource control
+#define B_PCH_PCR_DMI_V1CTL_EN BIT31
+#define B_PCH_PCR_DMI_V1CTL_ID (0x0F << 24) ///< Bit[27:24]
+#define N_PCH_PCR_DMI_V1CTL_ID 24
+#define V_PCH_PCR_DMI_V1CTL_ETVM_MASK 0xFC00
+#define V_PCH_PCR_DMI_V1CTL_TVM_MASK 0xFE
+#define R_PCH_PCR_DMI_V1STS 0x2026 ///< Virtual channel 1 status
+#define B_PCH_PCR_DMI_V1STS_NP BIT1
+#define R_PCH_PCR_DMI_VMCTL 0x2040 ///< ME Virtual Channel (VCm) resource control
+#define R_PCH_PCR_DMI_VMSTS 0x2046 ///< ME Virtual Channel Resource Status
+#define R_PCH_PCR_DMI_UEM 0x2088 ///< Uncorrectable Error Mask
+#define R_PCH_PCR_DMI_REC 0x20AC ///< Root Error Command
+
+//
+// Internal Link Configuration (DMI Only)
+//
+#define R_PCH_PCR_DMI_LCAP 0x21A4 ///< Link Capabilities
+#define B_PCH_PCR_DMI_LCAP_EL1 (BIT17 | BIT16 | BIT15)
+#define B_PCH_PCR_DMI_LCAP_EL0 (BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_DMI_LCAP_APMS (BIT11 | BIT10) ///< L0 is supported on DMI
+#define B_PCH_PCR_DMI_LCAP_MLW 0x000003F0
+#define B_PCH_PCR_DMI_LCAP_MLS 0x0000000F
+#define R_PCH_PCR_DMI_LCTL 0x21A8 ///< Link Control
+#define B_PCH_PCR_DMI_LCTL_ES BIT7
+#define B_PCH_PCR_DMI_LCTL_ASPM (BIT1 | BIT0) ///< Link ASPM
+#define R_PCH_PCR_DMI_LSTS 0x21AA ///< Link Status
+#define R_PCH_PCR_DMI_LCTL2 0x21B0 ///< Link Control 2
+#define R_PCH_PCR_DMI_LSTS2 0x21B2 ///< Link Status 2
+#define R_PCH_PCR_DMI_L01EC 0x21BC ///< Lane 0 and Lane 1 Equalization Control
+#define R_PCH_PCR_DMI_L23EC 0x21C0 ///< Lane 2 and Lane 3 Equalization Control
+#define B_PCH_PCR_DMI_UPL13RPH 0x0F000000 ///< Upstream Port Lane 1/3 Transmitter Preset Hint mask
+#define N_PCH_PCR_DMI_UPL13RPH 24 ///< Upstream Port Lane 1/3 Transmitter Preset Hint value offset
+#define B_PCH_PCR_DMI_UPL02RPH 0x000000F0 ///< Upstream Port Lane 0/2 Transmitter Preset Hint mask
+#define N_PCH_PCR_DMI_UPL02RPH 8 ///< Upstream Port Lane 0/2 Transmitter Preset Hint value offset
+#define V_PCH_PCR_DMI_UPL0RPH 7 ///< Upstream Port Lane 0 Transmitter Preset Hint value
+#define V_PCH_PCR_DMI_UPL1RPH 7 ///< Upstream Port Lane 1 Transmitter Preset Hint value
+#define V_PCH_PCR_DMI_UPL2RPH 7 ///< Upstream Port Lane 2 Transmitter Preset Hint value
+#define V_PCH_PCR_DMI_UPL3RPH 7 ///< Upstream Port Lane 3 Transmitter Preset Hint value
+
+
+//
+// North Port Error Injection Configuration (DMI Only)
+//
+#define R_PCH_PCR_DMI_DMIEN 0x2230 ///< DMI Error Injection Enable
+
+//
+// DMI Control
+//
+#define R_PCH_PCR_DMI_DMIC 0x2234 ///< DMI Control
+#define B_PCH_PCR_DMI_DMIC_SRL BIT31 ///< Secured register lock
+#define B_PCH_PCR_DMI_DMIC_ORCE (BIT25 | BIT24) ///< Offset Re-Calibration Enable
+#define N_PCH_PCR_DMI_DMIC_ORCE 24
+#define V_PCH_PCR_DMI_DMIC_ORCE_EN_GEN2_GEN3 1 ///< Enable offset re-calibration for Gen 2 and Gen 3 data rate only.
+#define B_PCH_PCR_DMI_DMIC_DMICGEN (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) ///< DMI Clock Gate Enable
+#define R_PCH_PCR_DMI_DMIHWAWC 0x2238 ///< DMI HW Autonomus Width Control
+#define R_PCH_PCR_DMI_IOSFSBCS 0x223E ///< IOSF Sideband Control and Status
+#define B_PCH_PCR_DMI_IOSFSBCS_DMICGEN (BIT6 | BIT5 | BIT3 | BIT2) ///< DMI Clock Gate Enable
+
+#define R_PCH_PCR_DMI_2300 0x2300
+#define R_PCH_PCR_DMI_2304 0x2304
+#define R_PCH_PCR_DMI_2310 0x2310
+#define R_PCH_PCR_DMI_2314 0x2314
+#define R_PCH_PCR_DMI_2320 0x2320
+#define R_PCH_PCR_DMI_2324 0x2324
+#define R_PCH_PCR_DMI_232C 0x232C
+#define R_PCH_PCR_DMI_2334 0x2334
+#define R_PCH_PCR_DMI_2338 0x2338
+#define R_PCH_PCR_DMI_2340 0x2340
+#define R_PCH_PCR_DMI_2344 0x2344
+#define R_PCH_PCR_DMI_2348 0x2348
+#define R_PCH_PCR_DMI_234C 0x234C
+
+//
+// Port Configuration Extension(DMI Only)
+//
+#define R_PCH_PCR_DMI_EQCFG1 0x2450
+#define B_PCH_PCR_DMI_EQCFG1_RTLEPCEB BIT16
+#define R_PCH_PCR_DMI_LTCO1 0x2470 ///< Local Transmitter Coefficient Override 1
+#define R_PCH_PCR_DMI_LTCO2 0x2474 ///< Local Transmitter Coefficient Override 2
+#define B_PCH_PCR_DMI_L13TCOE BIT25 ///< Lane 1/3 Transmitter Coefficient Override Enable
+#define B_PCH_PCR_DMI_L02TCOE BIT24 ///< Lane 0/2 Transmitter Coefficient Override Enable
+#define B_PCH_PCR_DMI_L13TPOSTCO 0x00fc0000 ///< Lane 1/3 Transmitter Post-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L13TPOSTCO 18 ///< Lane 1/3 Transmitter Post-Cursor Coefficient Override value offset
+#define B_PCH_PCR_DMI_L13TPRECO 0x0003f000 ///< Lane 1/3 Transmitter Pre-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L13TPRECO 12 ///< Lane 1/3 Transmitter Pre-Cursor Coefficient Override value offset
+#define B_PCH_PCR_DMI_L02TPOSTCO 0x00000fc0 ///< Lane 0/2 Transmitter Post-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L02TPOSTCO 6 ///< Lane 0/2 Transmitter Post-Cursor Coefficient Override value offset
+#define B_PCH_PCR_DMI_L02TPRECO 0x0000003f ///< Lane 0/2 Transmitter Pre-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L02TPRECO 0 ///< Lane 0/2 Transmitter Pre-Cursor Coefficient Override value offset
+#define R_PCH_PCR_DMI_G3L0SCTL 0x2478 ///< GEN3 L0s Control
+
+//
+// OP-DMI Specific Registers (OP-DMI Only)
+//
+#define R_PCH_PCR_OPDMI_LCTL 0x2600 ///< Link Control
+#define R_PCH_PCR_OPDMI_STC 0x260C ///< Sideband Timing Control
+#define R_PCH_PCR_OPDMI_LPMC 0x2614 ///< Link Power Management Control
+#define R_PCH_PCR_OPDMI_LCFG 0x2618 ///< Link Configuration
+
+//
+// DMI Source Decode PCRs (Common)
+//
+#define R_PCH_PCR_DMI_PCIEPAR1E 0x2700 ///< PCIE Port IOxAPIC Range 1 Enable
+#define R_PCH_PCR_DMI_PCIEPAR2E 0x2704 ///< PCIE Port IOxAPIC Range 2 Enable
+#define R_PCH_PCR_DMI_PCIEPAR3E 0x2708 ///< PCIE Port IOxAPIC Range 3 Enable
+#define R_PCH_PCR_DMI_PCIEPAR4E 0x270C ///< PCIE Port IOxAPIC Range 4 Enable
+#define R_PCH_PCR_DMI_PCIEPAR1DID 0x2710 ///< PCIE Port IOxAPIC Range 1 Destination ID
+#define R_PCH_PCR_DMI_PCIEPAR2DID 0x2714 ///< PCIE Port IOxAPIC Range 2 Destination ID
+#define R_PCH_PCR_DMI_PCIEPAR3DID 0x2718 ///< PCIE Port IOxAPIC Range 3 Destination ID
+#define R_PCH_PCR_DMI_PCIEPAR4DID 0x271C ///< PCIE Port IOxAPIC Range 4 Destination ID
+#define R_PCH_PCR_DMI_P2SBIOR 0x2720 ///< P2SB IO Range
+#define R_PCH_PCR_DMI_TTTBARB 0x2724 ///< Thermal Throttling BIOS Assigned Thermal Base Address
+#define R_PCH_PCR_DMI_TTTBARBH 0x2728 ///< Thermal Throttling BIOS Assigned Thermal Base High Address
+#define R_PCH_PCR_DMI_LPCLGIR1 0x2730 ///< LPC Generic I/O Range 1
+#define R_PCH_PCR_DMI_LPCLGIR2 0x2734 ///< LPC Generic I/O Range 2
+#define R_PCH_PCR_DMI_LPCLGIR3 0x2738 ///< LPC Generic I/O Range 3
+#define R_PCH_PCR_DMI_LPCLGIR4 0x273C ///< LPC Generic I/O Range 4
+#define R_PCH_PCR_DMI_LPCGMR 0x2740 ///< LPC Generic Memory Range
+#define R_PCH_PCR_DMI_LPCBDE 0x2744 ///< LPC BIOS Decode Enable
+#define R_PCH_PCR_DMI_UCPR 0x2748 ///< uCode Patch Region
+#define B_PCH_PCR_DMI_UCPR_UPRE BIT0 ///< uCode Patch Region Enable
+#define R_PCH_PCR_DMI_GCS 0x274C ///< Generic Control and Status
+#define B_PCH_PCR_DMI_RPRDID 0xFFFF0000 ///< RPR Destination ID
+#define B_PCH_PCR_DMI_BBS BIT10 ///< Boot BIOS Strap
+#define B_PCH_PCR_DMI_RPR BIT11 ///< Reserved Page Route
+#define B_PCH_PCR_DMI_BILD BIT0 ///< BIOS Interface Lock-Down
+#define R_PCH_PCR_DMI_IOT1 0x2750 ///< I/O Trap Register 1
+#define R_PCH_PCR_DMI_IOT2 0x2758 ///< I/O Trap Register 2
+#define R_PCH_PCR_DMI_IOT3 0x2760 ///< I/O Trap Register 3
+#define R_PCH_PCR_DMI_IOT4 0x2768 ///< I/O Trap Register 4
+#define R_PCH_PCR_DMI_LPCIOD 0x2770 ///< LPC I/O Decode Ranges
+#define R_PCH_PCR_DMI_LPCIOE 0x2774 ///< LPC I/O Enables
+#define R_PCH_PCR_DMI_TCOBASE 0x2778 ///< TCO Base Address
+#define B_PCH_PCR_DMI_TCOBASE_TCOBA 0xFFE0 ///< TCO Base Address Mask
+#define R_PCH_PCR_DMI_GPMR1 0x277C ///< General Purpose Memory Range 1
+#define R_PCH_PCR_DMI_GPMR1DID 0x2780 ///< General Purpose Memory Range 1 Destination ID
+#define R_PCH_PCR_DMI_GPMR2 0x2784 ///< General Purpose Memory Range 2
+#define R_PCH_PCR_DMI_GPMR2DID 0x2788 ///< General Purpose Memory Range 2 Destination ID
+#define R_PCH_PCR_DMI_GPMR3 0x278C ///< General Purpose Memory Range 3
+#define R_PCH_PCR_DMI_GPMR3DID 0x2790 ///< General Purpose Memory Range 3 Destination ID
+#define R_PCH_PCR_DMI_GPIOR1 0x2794 ///< General Purpose I/O Range 1
+#define R_PCH_PCR_DMI_GPIOR1DID 0x2798 ///< General Purpose I/O Range 1 Destination ID
+#define R_PCH_PCR_DMI_GPIOR2 0x279C ///< General Purpose I/O Range 2
+#define R_PCH_PCR_DMI_GPIOR2DID 0x27A0 ///< General Purpose I/O Range 2 Destination ID
+#define R_PCH_PCR_DMI_GPIOR3 0x27A4 ///< General Purpose I/O Range 3
+#define R_PCH_PCR_DMI_GPIOR3DID 0x27A8 ///< General Purpose I/O Range 3 Destination ID
+#define R_PCH_PCR_DMI_PMBASEA 0x27AC ///< PM Base Address
+#define R_PCH_PCR_DMI_PMBASEC 0x27B0 ///< PM Base Control
+#define R_PCH_PCR_DMI_ACPIBA 0x27B4 ///< ACPI Base Address
+#define R_PCH_PCR_DMI_ACPIBDID 0x27B8 ///< ACPI Base Destination ID
+
+
+//
+// Opi PHY registers
+//
+#define R_PCH_PCR_OPIPHY_0110 0x0110
+#define R_PCH_PCR_OPIPHY_0118 0x0118
+#define R_PCH_PCR_OPIPHY_011C 0x011C
+#define R_PCH_PCR_OPIPHY_0354 0x0354
+#define R_PCH_PCR_OPIPHY_B104 0xB104
+#define R_PCH_PCR_OPIPHY_B10C 0xB10C
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h
new file mode 100644
index 0000000000..c9e08ca854
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h
@@ -0,0 +1,123 @@
+/** @file
+ Register definition for FIA component
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_FIA_H_
+#define _PCH_REGS_FIA_H_
+
+
+//
+// Private chipset regsiter (Memory space) offset definition
+// The PCR register defines is used for PCR MMIO programming and PCH SBI programming as well.
+//
+
+//
+// PID:FIA
+//
+#define SKL_PCH_MAX_FIA_DRCRM 3
+#define KBL_PCH_MAX_FIA_DRCRM 4
+#define PCH_MAX_FIA_DRCRM KBL_PCH_MAX_FIA_DRCRM
+#define R_PCH_PCR_FIA_CC 0
+#define B_PCH_PCR_FIA_CC_SRL BIT31
+#define B_PCH_PCR_FIA_CC_PTOCGE BIT17
+#define B_PCH_PCR_FIA_CC_OSCDCGE BIT16
+#define B_PCH_PCR_FIA_CC_SCPTCGE BIT15
+
+#define R_PCH_PCR_FIA_PLLCTL 0x20
+#define R_PCH_PCR_FIA_DRCRM1 0x100
+#define R_PCH_PCR_FIA_DRCRM2 0x104
+#define R_PCH_PCR_FIA_DRCRM3 0x108
+#define R_PCH_PCR_FIA_DRCRM4 0x10C // KBL-H only
+#define N_PCH_PCR_FIA_DRCRM_GBEPCKRQM 23
+#define S_PCH_PCR_FIA_DRCRM_BITS_PER_FIELD 4 // CLKREQ number is encoded in 4 bits
+#define S_PCH_PCR_FIA_DRCRM_FIELDS_PER_REG 8 // each DRCRM register contains bitfields for 8 rootports
+#define V_PCH_PCR_FIA_DRCRM_NO_CLKREQ 0 // ClkReq not present
+#define S_PCH_PCR_FIA_DRCRM 4
+#define R_PCH_PCR_FIA_STRPFUSECFG1_REG_BASE 0x200
+#define B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIE_PEN BIT31
+#define B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL (BIT30 | BIT29 | BIT28)
+#define N_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL 28
+#define R_PCH_PCR_FIA_PCIESATA_FUSECFG_REG_BASE 0x204
+#define R_PCH_PCR_FIA_PCIESATA_STRPCFG_REG_BASE 0x208
+#define R_PCH_PCR_FIA_PCIEUSB3_STRPFUSECFG_REG_BASE 0x20C
+#define R_PCH_PCR_FIA_EXP_FUSECFG_REG_BASE 0x210
+#define R_PCH_PCR_FIA_USB3SSIC_STRPFUSECFG_REG_BASE 0x214
+#define R_PCH_PCR_FIA_CSI3_STRPFUSECFG_REG_BASE 0x218
+#define R_PCH_PCR_FIA_USB3SATA_STRPFUSECFG_REG_BASE 0x21C
+#define R_PCH_PCR_FIA_UFS_STRPFUSECFG_REG_BASE 0x220
+#define R_PCH_PCR_FIA_LOS1_REG_BASE 0x250
+#define R_PCH_PCR_FIA_LOS2_REG_BASE 0x254
+#define R_PCH_PCR_FIA_LOS3_REG_BASE 0x258
+#define R_PCH_PCR_FIA_LOS4_REG_BASE 0x25C
+#define V_PCH_PCR_FIA_LANE_OWN_PCIEDMI 0x0
+#define V_PCH_PCR_FIA_LANE_OWN_USB3 0x1
+#define V_PCH_PCR_FIA_LANE_OWN_SATA 0x2
+#define V_PCH_PCR_FIA_LANE_OWN_GBE 0x3
+#define V_PCH_PCR_FIA_LANE_OWN_MOBEXP 0x4
+#define V_PCH_PCR_FIA_LANE_OWN_SSIC 0x5
+#define V_PCH_PCR_FIA_LANE_OWN_CSI3 0x6
+#define V_PCH_PCR_FIA_LANE_OWN_UFS 0x7
+#define B_PCH_PCR_FIA_L0O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L1O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L2O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L3O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L4O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L5O (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_PCR_FIA_L6O (BIT27 | BIT26 | BIT25 | BIT24)
+#define B_PCH_PCR_FIA_L7O (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_PCR_FIA_L8O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L9O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L10O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L11O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L12O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L13O (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_PCR_FIA_L14O (BIT27 | BIT26 | BIT25 | BIT24)
+#define B_PCH_PCR_FIA_L15O (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_PCR_FIA_L16O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L17O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L18O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L19O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L20O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L21O (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_PCR_FIA_L22O (BIT27 | BIT26 | BIT25 | BIT24)
+#define B_PCH_PCR_FIA_L23O (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_PCR_FIA_L24O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L25O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L26O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L27O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L28O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L29O (BIT23 | BIT22 | BIT21 | BIT20)
+#define PCH_H_FIA_DMILANE_START 14
+#define PCH_H_FIA_DMILANE_END 17
+#define PCH_FIA_MAX_LANES 34
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h
new file mode 100644
index 0000000000..a6b2c4a8e5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h
@@ -0,0 +1,529 @@
+/** @file
+ Register names for PCH GPIO
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_GPIO_H_
+#define _PCH_REGS_GPIO_H_
+
+#define V_PCH_GPIO_GPP_A_PAD_MAX 24
+#define V_PCH_GPIO_GPP_B_PAD_MAX 24
+#define V_PCH_GPIO_GPP_C_PAD_MAX 24
+#define V_PCH_GPIO_GPP_D_PAD_MAX 24
+#define V_PCH_GPIO_GPP_E_PAD_MAX V_PCH_LP_GPIO_GPP_E_PAD_MAX
+#define V_PCH_LP_GPIO_GPP_E_PAD_MAX 24
+#define V_PCH_H_GPIO_GPP_E_PAD_MAX 13
+#define V_PCH_GPIO_GPP_F_PAD_MAX 24
+#define V_PCH_GPIO_GPP_G_PAD_MAX V_PCH_H_GPIO_GPP_G_PAD_MAX
+#define V_PCH_LP_GPIO_GPP_G_PAD_MAX 8
+#define V_PCH_H_GPIO_GPP_G_PAD_MAX 24
+#define V_PCH_H_GPIO_GPP_H_PAD_MAX 24
+#define V_PCH_H_GPIO_GPP_I_PAD_MAX 11
+#define V_PCH_GPIO_GPD_PAD_MAX 12
+
+#define V_PCH_GPIO_GROUP_MAX 10
+#define V_PCH_H_GPIO_GROUP_MAX 10
+#define V_PCH_LP_GPIO_GROUP_MAX 8
+#define V_PCH_GPIO_NUM_SUPPORTED_GPIS 204
+#define S_PCH_GPIO_GP_SMI_EN 4
+#define S_PCH_GPIO_GP_SMI_STS 4
+
+///
+/// Groups mapped to 2-tier General Purpose Event will all be under
+/// one master GPE_111 (0x6F)
+///
+#define PCH_GPIO_2_TIER_MASTER_GPE_NUMBER 0x6F
+
+
+//
+// GPIO Common Private Configuration Registers
+//
+#define R_PCH_PCR_GPIO_REV_ID 0x00
+#define R_PCH_PCR_GPIO_CAP_LIST 0x04
+#define R_PCH_PCR_GPIO_FAMBAR 0x08
+#define R_PCH_PCR_GPIO_PADBAR 0x0C
+#define B_PCH_PCR_GPIO_PADBAR 0x0000FFFF
+#define R_PCH_PCR_GPIO_MISCCFG 0x10
+#define B_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 (BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 16
+#define B_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 (BIT15 | BIT14 | BIT13 | BIT12)
+#define N_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 12
+#define B_PCH_PCR_GPIO_MISCCFG_GPE0_DW0 (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_PCR_GPIO_MISCCFG_GPE0_DW0 8
+#define B_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE BIT3
+#define N_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE 3
+#define B_PCH_PCR_GPIO_MISCCFG_GPDPCGEN BIT1
+#define B_PCH_PCR_GPIO_MISCCFG_GPDLCGEN BIT0
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_MISCSECCFG 0x14
+
+//
+// GPIO Community 0 Private Configuration Registers
+//
+// SKL PCH-LP
+#define R_PCH_LP_PCR_GPIO_GPP_A_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPP_B_PAD_OWN 0x30
+#define R_PCH_LP_PCR_GPIO_GPP_A_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPP_B_GPI_VWM_EN 0x84
+#define R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX 0xA4
+#define R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK 0xA8
+#define R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX 0xAC
+// SKL PCH-H
+#define R_PCH_H_PCR_GPIO_GPP_A_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPP_B_PAD_OWN 0x2C
+#define R_PCH_H_PCR_GPIO_GPP_A_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPP_B_GPI_VWM_EN 0x74
+#define R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX 0x94
+#define R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK 0x98
+#define R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX 0x9C
+// Common
+#define R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN 0xD0
+#define R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN 0xD4
+#define R_PCH_PCR_GPIO_GPP_A_GPI_IS 0x0100
+#define R_PCH_PCR_GPIO_GPP_B_GPI_IS 0x0104
+#define R_PCH_PCR_GPIO_GPP_A_GPI_IE 0x0120
+#define R_PCH_PCR_GPIO_GPP_B_GPI_IE 0x0124
+#define R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS 0x0140
+#define R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS 0x0144
+#define R_PCH_PCR_GPIO_GPP_A_GPI_GPE_EN 0x0160
+#define R_PCH_PCR_GPIO_GPP_B_GPI_GPE_EN 0x0164
+#define R_PCH_PCR_GPIO_GPP_A_SMI_STS 0x0180
+#define R_PCH_PCR_GPIO_GPP_B_SMI_STS 0x0184
+#define R_PCH_PCR_GPIO_GPP_A_SMI_EN 0x01A0
+#define R_PCH_PCR_GPIO_GPP_B_SMI_EN 0x01A4
+#define R_PCH_PCR_GPIO_GPP_A_NMI_STS 0x01C0
+#define R_PCH_PCR_GPIO_GPP_B_NMI_STS 0x01C4
+#define R_PCH_PCR_GPIO_GPP_A_NMI_EN 0x01E0
+#define R_PCH_PCR_GPIO_GPP_B_NMI_EN 0x01E4
+#define R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET 0x400
+#define R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET 0x4C0
+
+//
+// GPIO Community 1 Private Configuration Registers
+//
+//SKL PCH-LP:
+#define R_PCH_LP_PCR_GPIO_GPP_C_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPP_D_PAD_OWN 0x30
+#define R_PCH_LP_PCR_GPIO_GPP_E_PAD_OWN 0x40
+#define R_PCH_LP_PCR_GPIO_GPP_C_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPP_D_GPI_VWM_EN 0x84
+#define R_PCH_LP_PCR_GPIO_GPP_E_GPI_VWM_EN 0x88
+#define R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX 0xA4
+#define R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK 0xA8
+#define R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX 0xAC
+#define R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK 0xB0
+#define R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX 0xB4
+//SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_C_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPP_D_PAD_OWN 0x2C
+#define R_PCH_H_PCR_GPIO_GPP_E_PAD_OWN 0x38
+#define R_PCH_H_PCR_GPIO_GPP_F_PAD_OWN 0x40
+#define R_PCH_H_PCR_GPIO_GPP_G_PAD_OWN 0x4C
+#define R_PCH_H_PCR_GPIO_GPP_H_PAD_OWN 0x58
+#define R_PCH_H_PCR_GPIO_GPP_C_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPP_D_GPI_VWM_EN 0x74
+#define R_PCH_H_PCR_GPIO_GPP_E_GPI_VWM_EN 0x78
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_VWM_EN 0x7C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_VWM_EN 0x80
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_VWM_EN 0x84
+#define R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX 0x94
+#define R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK 0x98
+#define R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX 0x9C
+#define R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK 0xA0
+#define R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX 0xA4
+#define R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK 0xA8
+#define R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX 0xAC
+#define R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK 0xB0
+#define R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX 0xB4
+#define R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK 0xB8
+#define R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX 0xBC
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN 0xD0
+#define R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN 0xD4
+#define R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN 0xD8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_HOSTSW_OWN 0xDC
+#define R_PCH_H_PCR_GPIO_GPP_G_HOSTSW_OWN 0xE0
+#define R_PCH_H_PCR_GPIO_GPP_H_HOSTSW_OWN 0xE4
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_IS 0x0100
+#define R_PCH_PCR_GPIO_GPP_D_GPI_IS 0x0104
+#define R_PCH_PCR_GPIO_GPP_E_GPI_IS 0x0108
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_IS 0x010C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_IS 0x0110
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_IS 0x0114
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_IE 0x0120
+#define R_PCH_PCR_GPIO_GPP_D_GPI_IE 0x0124
+#define R_PCH_PCR_GPIO_GPP_E_GPI_IE 0x0128
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_IE 0x012C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_IE 0x0130
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_IE 0x0134
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS 0x0140
+#define R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS 0x0144
+#define R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS 0x0148
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_STS 0x014C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_STS 0x0150
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_STS 0x0154
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_GPE_EN 0x0160
+#define R_PCH_PCR_GPIO_GPP_D_GPI_GPE_EN 0x0164
+#define R_PCH_PCR_GPIO_GPP_E_GPI_GPE_EN 0x0168
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_EN 0x016C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_EN 0x0170
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_EN 0x0174
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_SMI_STS 0x0180
+#define R_PCH_PCR_GPIO_GPP_D_SMI_STS 0x0184
+#define R_PCH_PCR_GPIO_GPP_E_SMI_STS 0x0188
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_SMI_STS 0x018C
+#define R_PCH_H_PCR_GPIO_GPP_G_SMI_STS 0x0190
+#define R_PCH_H_PCR_GPIO_GPP_H_SMI_STS 0x0194
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_SMI_EN 0x01A0
+#define R_PCH_PCR_GPIO_GPP_D_SMI_EN 0x01A4
+#define R_PCH_PCR_GPIO_GPP_E_SMI_EN 0x01A8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_SMI_EN 0x01AC
+#define R_PCH_H_PCR_GPIO_GPP_G_SMI_EN 0x01B0
+#define R_PCH_H_PCR_GPIO_GPP_H_SMI_EN 0x01B4
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_NMI_STS 0x01C0
+#define R_PCH_PCR_GPIO_GPP_D_NMI_STS 0x01C4
+#define R_PCH_PCR_GPIO_GPP_E_NMI_STS 0x01C8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_NMI_STS 0x01CC
+#define R_PCH_H_PCR_GPIO_GPP_G_NMI_STS 0x01D0
+#define R_PCH_H_PCR_GPIO_GPP_H_NMI_STS 0x01D4
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_NMI_EN 0x01E0
+#define R_PCH_PCR_GPIO_GPP_D_NMI_EN 0x01E4
+#define R_PCH_PCR_GPIO_GPP_E_NMI_EN 0x01E8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_NMI_EN 0x01EC
+#define R_PCH_H_PCR_GPIO_GPP_G_NMI_EN 0x01F0
+#define R_PCH_H_PCR_GPIO_GPP_H_NMI_EN 0x01F4
+// Common:
+#define R_PCH_PCR_GPIO_CAP_LIST_1_PWM 0x0200
+#define R_PCH_PCR_GPIO_PWMC 0x0204
+#define R_PCH_PCR_GPIO_CAP_LIST_2_SER_BLINK 0x0208
+#define R_PCH_PCR_GPIO_GP_SER_BLINK 0x020C
+#define B_PCH_PCR_GPIO_GP_SER_BLINK 0x1F
+#define R_PCH_PCR_GPIO_GP_SER_CMDSTS 0x0210
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_DLS (BIT23 | BIT22)
+#define N_PCH_PCR_GPIO_GP_SER_CMDSTS_DLS 22
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_DRS 0x003F0000
+#define N_PCH_PCR_GPIO_GP_SER_CMDSTS_DRS 16
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_BUSY BIT8
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_GO BIT0
+#define R_PCH_PCR_GPIO_GP_SER_DATA 0x0210
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GSX 0x218
+#define R_PCH_H_PCR_GPIO_GSX_CAP 0x21C
+#define R_PCH_H_PCR_GPIO_GSX_C0CAP_DW0 0x220
+#define R_PCH_H_PCR_GPIO_GSX_C0CAP_DW1 0x224
+#define R_PCH_H_PCR_GPIO_GSX_C0GPILVL_DW0 0x228
+#define R_PCH_H_PCR_GPIO_GSX_C0GPILVL_DW1 0x22C
+#define R_PCH_H_PCR_GPIO_GSX_C0GPOLVL_DW0 0x230
+#define R_PCH_H_PCR_GPIO_GSX_C0GPOLVL_DW1 0x234
+#define R_PCH_H_PCR_GPIO_GSX_C0CMD 0x238
+#define R_PCH_H_PCR_GPIO_GSX_C0CTM 0x23C
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET 0x400
+#define R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET 0x4C0
+#define R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET 0x580
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_PADCFG_OFFSET 0x5E8
+#define R_PCH_H_PCR_GPIO_GPP_G_PADCFG_OFFSET 0x6A8
+#define R_PCH_H_PCR_GPIO_GPP_H_PADCFG_OFFSET 0x768
+
+//
+// GPIO Community 2 Private Configuration Registers
+//
+// SKL PCH-LP
+#define R_PCH_LP_PCR_GPIO_GPD_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPD_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX 0xA4
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPD_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPD_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX 0x94
+// Common:
+#define R_PCH_PCR_GPIO_GPD_HOSTSW_OWN 0xD0
+#define R_PCH_PCR_GPIO_GPD_GPI_IS 0x0100
+#define R_PCH_PCR_GPIO_GPD_GPI_IE 0x0120
+#define R_PCH_PCR_GPIO_GPD_GPI_GPE_STS 0x0140
+#define R_PCH_PCR_GPIO_GPD_GPI_GPE_EN 0x0160
+#define R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET 0x400
+//
+// GPIO Community 3 Private Configuration Registers
+//
+// SKL PCH-LP:
+#define R_PCH_LP_PCR_GPIO_GPP_F_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPP_G_PAD_OWN 0x30
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_VWM_EN 0x84
+#define R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX 0xA4
+#define R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK 0xA8
+#define R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX 0xAC
+#define R_PCH_LP_PCR_GPIO_GPP_F_HOSTSW_OWN 0xD0
+#define R_PCH_LP_PCR_GPIO_GPP_G_HOSTSW_OWN 0xD4
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_IS 0x0100
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_IS 0x0104
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_IE 0x0120
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_IE 0x0124
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_STS 0x0140
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_STS 0x0144
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_EN 0x0160
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_EN 0x0164
+#define R_PCH_LP_PCR_GPIO_GPP_F_PADCFG_OFFSET 0x400
+#define R_PCH_LP_PCR_GPIO_GPP_G_PADCFG_OFFSET 0x4C0
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_I_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX 0x94
+#define R_PCH_H_PCR_GPIO_GPP_I_HOSTSW_OWN 0xD0
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_IS 0x0100
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_IE 0x0120
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_STS 0x0140
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_EN 0x0160
+#define R_PCH_H_PCR_GPIO_GPP_I_SMI_STS 0x0180
+#define R_PCH_H_PCR_GPIO_GPP_I_SMI_EN 0x01A0
+#define R_PCH_H_PCR_GPIO_GPP_I_NMI_STS 0x01C0
+#define R_PCH_H_PCR_GPIO_GPP_I_NMI_EN 0x01E0
+#define R_PCH_H_PCR_GPIO_GPP_I_PADCFG_OFFSET 0x400
+
+//
+// Define Pad Number
+//
+#define V_GPIO_PAD0 0
+#define V_GPIO_PAD1 1
+#define V_GPIO_PAD2 2
+#define V_GPIO_PAD3 3
+#define V_GPIO_PAD4 4
+#define V_GPIO_PAD5 5
+#define V_GPIO_PAD6 6
+#define V_GPIO_PAD7 7
+#define V_GPIO_PAD8 8
+#define V_GPIO_PAD9 9
+#define V_GPIO_PAD10 10
+#define V_GPIO_PAD11 11
+#define V_GPIO_PAD12 12
+#define V_GPIO_PAD13 13
+#define V_GPIO_PAD14 14
+#define V_GPIO_PAD15 15
+#define V_GPIO_PAD16 16
+#define V_GPIO_PAD17 17
+#define V_GPIO_PAD18 18
+#define V_GPIO_PAD19 19
+#define V_GPIO_PAD20 20
+#define V_GPIO_PAD21 21
+#define V_GPIO_PAD22 22
+#define V_GPIO_PAD23 23
+
+//
+// Host Software Pad Ownership modes
+//
+#define V_PCH_PCR_GPIO_HOSTSW_OWN_ACPI 0x00
+#define V_PCH_PCR_GPIO_HOSTSW_OWN_GPIO 0x01
+
+//
+// Pad Ownership modes
+//
+#define V_PCH_PCR_GPIO_PAD_OWN_HOST 0x00
+#define V_PCH_PCR_GPIO_PAD_OWN_CSME 0x01
+#define V_PCH_PCR_GPIO_PAD_OWN_ISH 0x02
+
+//
+// Pad Configuration Register DW0
+//
+
+//Pad Reset Config
+#define B_PCH_GPIO_RST_CONF (BIT31 | BIT30)
+#define N_PCH_GPIO_RST_CONF 30
+#define V_PCH_GPIO_RST_CONF_POW_GOOD 0x00
+#define V_PCH_GPIO_RST_CONF_DEEP_RST 0x01
+#define V_PCH_GPIO_RST_CONF_GPIO_RST 0x02
+#define V_PCH_GPIO_RST_CONF_RESUME_RST 0x03 // Only for GPD Group
+
+//RX Pad State Select
+#define B_PCH_GPIO_RX_PAD_STATE BIT29
+#define N_PCH_GPIO_RX_PAD_STATE 29
+#define V_PCH_GPIO_RX_PAD_STATE_RAW 0x00
+#define V_PCH_GPIO_RX_PAD_STATE_INT 0x01
+
+//RX Raw Overrride to 1
+#define B_PCH_GPIO_RX_RAW1 BIT28
+#define N_PCH_GPIO_RX_RAW1 28
+#define V_PCH_GPIO_RX_RAW1_DIS 0x00
+#define V_PCH_GPIO_RX_RAW1_EN 0x01
+
+//RX Level/Edge Configuration
+#define B_PCH_GPIO_RX_LVL_EDG (BIT26 | BIT25)
+#define N_PCH_GPIO_RX_LVL_EDG 25
+#define V_PCH_GPIO_RX_LVL_EDG_LVL 0x00
+#define V_PCH_GPIO_RX_LVL_EDG_EDG 0x01
+#define V_PCH_GPIO_RX_LVL_EDG_0 0x02
+#define V_PCH_GPIO_RX_LVL_EDG_RIS_FAL 0x03
+
+//RX Invert
+#define B_PCH_GPIO_RXINV BIT23
+#define N_PCH_GPIO_RXINV 23
+#define V_PCH_GPIO_RXINV_NO 0x00
+#define V_PCH_GPIO_RXINV_YES 0x01
+
+//GPIO Input Route IOxAPIC
+#define B_PCH_GPIO_RX_APIC_ROUTE BIT20
+#define N_PCH_GPIO_RX_APIC_ROUTE 20
+#define V_PCH_GPIO_RX_APIC_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_APIC_ROUTE_EN 0x01
+
+//GPIO Input Route SCI
+#define B_PCH_GPIO_RX_SCI_ROUTE BIT19
+#define N_PCH_GPIO_RX_SCI_ROUTE 19
+#define V_PCH_GPIO_RX_SCI_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_SCI_ROUTE_EN 0x01
+
+//GPIO Input Route SMI
+#define B_PCH_GPIO_RX_SMI_ROUTE BIT18
+#define N_PCH_GPIO_RX_SMI_ROUTE 18
+#define V_PCH_GPIO_RX_SMI_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_SMI_ROUTE_EN 0x01
+
+//GPIO Input Route NMI
+#define B_PCH_GPIO_RX_NMI_ROUTE BIT17
+#define N_PCH_GPIO_RX_NMI_ROUTE 17
+#define V_PCH_GPIO_RX_NMI_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_NMI_ROUTE_EN 0x01
+
+//GPIO Pad Mode
+#define B_PCH_GPIO_PAD_MODE (BIT12 | BIT11 | BIT10)
+#define N_PCH_GPIO_PAD_MODE 10
+#define V_PCH_GPIO_PAD_MODE_GPIO 0
+#define V_PCH_GPIO_PAD_MODE_NAT_1 1
+#define V_PCH_GPIO_PAD_MODE_NAT_2 2
+#define V_PCH_GPIO_PAD_MODE_NAT_3 3
+#define V_PCH_GPIO_PAD_MODE_NAT_4 4 // SPT-H only
+
+//GPIO RX Disable
+#define B_PCH_GPIO_RXDIS BIT9
+#define N_PCH_GPIO_RXDIS 9
+#define V_PCH_GPIO_RXDIS_EN 0x00
+#define V_PCH_GPIO_RXDIS_DIS 0x01
+
+//GPIO TX Disable
+#define B_PCH_GPIO_TXDIS BIT8
+#define N_PCH_GPIO_TXDIS 8
+#define V_PCH_GPIO_TXDIS_EN 0x00
+#define V_PCH_GPIO_TXDIS_DIS 0x01
+
+//GPIO RX State
+#define B_PCH_GPIO_RX_STATE BIT1
+#define N_PCH_GPIO_RX_STATE 1
+#define V_PCH_GPIO_RX_STATE_LOW 0x00
+#define V_PCH_GPIO_RX_STATE_HIGH 0x01
+
+//GPIO TX State
+#define B_PCH_GPIO_TX_STATE BIT0
+#define N_PCH_GPIO_TX_STATE 0
+#define V_PCH_GPIO_TX_STATE_LOW 0x00
+#define V_PCH_GPIO_TX_STATE_HIGH 0x01
+
+//
+// Pad Configuration Register DW1
+//
+
+//Padtol
+#define B_PCH_GPIO_PADTOL BIT25
+#define N_PCH_GPIO_PADTOL 25
+#define V_PCH_GPIO_PADTOL_NONE 0x00
+#define V_PCH_GPIO_PADTOL_CLEAR 0x00
+#define V_PCH_GPIO_PADTOL_SET 0x01
+
+//Termination
+#define B_PCH_GPIO_TERM (BIT13 | BIT12 | BIT11 | BIT10)
+#define N_PCH_GPIO_TERM 10
+#define V_PCH_GPIO_TERM_WPD_NONE 0x00
+#define V_PCH_GPIO_TERM_WPD_5K 0x02
+#define V_PCH_GPIO_TERM_WPD_20K 0x04
+#define V_PCH_GPIO_TERM_WPU_NONE 0x08
+#define V_PCH_GPIO_TERM_WPU_1K 0x09
+#define V_PCH_GPIO_TERM_WPU_2K 0x0B
+#define V_PCH_GPIO_TERM_WPU_5K 0x0A
+#define V_PCH_GPIO_TERM_WPU_20K 0x0C
+#define V_PCH_GPIO_TERM_WPU_1K_2K 0x0D
+#define V_PCH_GPIO_TERM_NATIVE 0x0F
+
+//Interrupt number
+#define B_PCH_GPIO_INTSEL 0x7F
+#define N_PCH_GPIO_INTSEL 0
+
+//
+// Ownership
+//
+#define V_PCH_GPIO_OWN_GPIO 0x01
+#define V_PCH_GPIO_OWN_ACPI 0x00
+
+//
+// GPE
+//
+#define V_PCH_GPIO_GPE_EN 0x01
+#define V_PCH_GPIO_GPE_DIS 0x00
+//
+// SMI
+//
+#define V_PCH_GPIO_SMI_EN 0x01
+#define V_PCH_GPIO_SMI_DIS 0x00
+//
+// NMI
+//
+#define V_PCH_GPIO_NMI_EN 0x01
+#define V_PCH_GPIO_NMI_DIS 0x00
+//
+// Reserved: RSVD1
+//
+#define V_PCH_GPIO_RSVD1 0x00
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h
new file mode 100644
index 0000000000..1d5c0e9e76
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h
@@ -0,0 +1,201 @@
+/** @file
+ Register names for PCH High Definition Audio device.
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_HDA_H_
+#define _PCH_REGS_HDA_H_
+
+//
+// HD-A Controller Registers (D31:F3)
+//
+// PCI Configuration Space Registers
+//
+#define PCI_DEVICE_NUMBER_PCH_HDA 31
+#define PCI_FUNCTION_NUMBER_PCH_HDA 3
+
+#define R_PCH_HDA_PI 0x09
+#define V_PCH_HDA_PI_ADSP_UAA 0x80
+#define R_PCH_HDA_SCC 0x0A
+#define V_PCH_HDA_SCC_ADSP 0x01
+#define R_PCH_HDA_HDALBA 0x10
+#define B_PCH_HDA_HDALBA_LBA 0xFFFFC000
+#define V_PCH_HDA_HDBAR_SIZE (1 << 14)
+#define R_PCH_HDA_HDAUBA 0x14
+#define B_PCH_HDA_HDAUBA_UBA 0xFFFFFFFF
+#define R_PCH_HDA_CGCTL 0x48
+#define B_PCH_HDA_CGCTL_SROTCGE BIT18
+#define B_PCH_HDA_CGCTL_MISCBDCGE BIT6
+#define R_PCH_HDA_PC 0x52
+#define V_PCH_HDA_PC_PMES 0x18
+#define N_PCH_HDA_PC_PMES 11
+#define R_PCH_HDA_PCS 0x54
+#define B_PCH_HDA_PCS_PMEE BIT8
+#define B_PCH_HDA_PCS_PS (BIT1 | BIT0)
+#define R_PCH_HDA_MMC 0x62
+#define B_PCH_HDA_MMC_ME BIT0
+#define R_PCH_HDA_DEVC 0x78
+#define B_PCH_HDA_DEVC_NSNPEN BIT11
+#define R_PCH_HDA_SEM1 0xC0
+#define B_PCH_HDA_SEM1_LFLCS BIT24
+#define B_PCH_HDA_SEM1_BLKC3DIS BIT17
+#define B_PCH_HDA_SEM1_TMODE BIT12
+#define B_PCH_HDA_SEM1_FIFORDYSEL (BIT10 | BIT9)
+#define R_PCH_HDA_SEM2 0xC4
+#define B_PCH_HDA_SEM2_BSMT (BIT27 | BIT26)
+#define V_PCH_HDA_SEM2_BSMT 0x1
+#define N_PCH_HDA_SEM2_BSMT 26
+#define B_PCH_HDA_SEM2_VC0PSNR BIT24
+#define B_PCH_HDA_SEM2_DUM BIT23
+#define R_PCH_HDA_SEM3L 0xC8
+#define B_PCH_HDA_SEM3L_ISL1EXT2 (BIT21 | BIT20)
+#define V_PCH_HDA_SEM3L_ISL1EXT2 0x2
+#define N_PCH_HDA_SEM3L_ISL1EXT2 20
+#define R_PCH_HDA_SEM4L 0xD0
+#define B_PCH_HDA_SEM4L_OSL1EXT2 (BIT21 | BIT20)
+#define V_PCH_HDA_SEM4L_OSL1EXT2 0x3
+#define N_PCH_HDA_SEM4L_OSL1EXT2 20
+
+//
+// Memory Space Registers
+//
+//
+// Resides in 'HD Audio Global Registers' (0000h)
+//
+#define R_PCH_HDABA_GCAP 0x00
+#define R_PCH_HDABA_GCTL 0x08
+#define B_PCH_HDABA_GCTL_CRST BIT0
+
+#define R_PCH_HDABA_OUTPAY 0x04
+#define R_PCH_HDABA_INPAY 0x06
+#define V_PCH_HDABA_INPAY_DEFAULT 0x1C
+
+#define R_PCH_HDABA_WAKEEN 0x0C
+#define B_PCH_HDABA_WAKEEN_SDI_3 BIT3
+#define B_PCH_HDABA_WAKEEN_SDI_2 BIT2
+#define B_PCH_HDABA_WAKEEN_SDI_1 BIT1
+#define B_PCH_HDABA_WAKEEN_SDI_0 BIT0
+
+#define R_PCH_HDABA_WAKESTS 0x0E
+#define B_PCH_HDABA_WAKESTS_SDIN3 BIT3
+#define B_PCH_HDABA_WAKESTS_SDIN2 BIT2
+#define B_PCH_HDABA_WAKESTS_SDIN1 BIT1
+#define B_PCH_HDABA_WAKESTS_SDIN0 BIT0
+
+//
+// Resides in 'HD Audio Controller Registers' (0030h)
+//
+#define R_PCH_HDABA_IC 0x60
+#define R_PCH_HDABA_IR 0x64
+#define R_PCH_HDABA_ICS 0x68
+#define B_PCH_HDABA_ICS_IRV BIT1
+#define B_PCH_HDABA_ICS_ICB BIT0
+
+//
+// Resides in 'HD Audio Processing Pipe Capability Structure' (0800h)
+//
+#define R_PCH_HDABA_PPC 0x0800 // Processing Pipe Capability Structure (Memory Space, offset 0800h)
+#define R_PCH_HDABA_PPCTL (R_PCH_HDABA_PPC + 0x04)
+#define B_PCH_HDABA_PPCTL_GPROCEN BIT30
+
+//
+// Resides in 'HD Audio Multiple Links Capability Structure' (0C00h)
+//
+#define V_PCH_HDA_HDALINK_INDEX 0
+#define V_PCH_HDA_IDISPLINK_INDEX 1
+
+#define R_PCH_HDABA_MLC 0x0C00 // Multiple Links Capability Structure (Memory Space, offset 0C00h)
+#define R_PCH_HDABA_LCTLX(x) (R_PCH_HDABA_MLC + (0x40 + (0x40 * (x)) + 0x04)) // x - Link index: 0 - HDA Link, 1 - iDisp Link
+#define B_PCH_HDABA_LCTLX_CPA BIT23
+#define B_PCH_HDABA_LCTLX_SPA BIT16
+#define N_PCH_HDABA_LCTLX_SCF 0
+#define V_PCH_HDABA_LCTLX_SCF_6MHZ 0x0
+#define V_PCH_HDABA_LCTLX_SCF_12MHZ 0x1
+#define V_PCH_HDABA_LCTLX_SCF_24MHZ 0x2
+#define V_PCH_HDABA_LCTLX_SCF_48MHZ 0x3
+#define V_PCH_HDABA_LCTLX_SCF_96MHZ 0x4
+
+//
+// Resides in 'HD Audio Vendor Specific Registers' (1000h)
+//
+#define R_PCH_HDABA_LTRC 0x1048
+#define V_PCH_HDABA_LTRC_GB 0x29
+#define N_PCH_HDABA_LTRC_GB 0
+#define R_PCH_HDABA_PCE 0x104B
+#define B_PCH_HDABA_PCE_D3HE BIT2
+
+//
+// Private Configuration Space Registers
+//
+//
+// Resides in IOSF & Fabric Configuration Registers (000h)
+//
+#define R_PCH_PCR_HDA_TTCCFG 0xE4
+#define B_PCH_PCR_HDA_TTCCFG_HCDT BIT1
+
+//
+// Resides in PCI & Codec Configuration Registers (500h)
+//
+#define R_PCH_PCR_HDA_PCICDCCFG 0x500 // PCI & Codec Configuration Registers (PCR, offset 500h)
+#define B_PCH_PCR_HDA_PCICDCCFG_ACPIIN 0x0000FF00
+#define N_PCH_PCR_HDA_PCICDCCFG_ACPIIN 8
+#define R_PCH_PCR_HDA_FNCFG (R_PCH_PCR_HDA_PCICDCCFG + 0x30)
+#define B_PCH_PCR_HDA_FNCFG_PGD BIT5
+#define B_PCH_PCR_HDA_FNCFG_BCLD BIT4
+#define B_PCH_PCR_HDA_FNCFG_CGD BIT3
+#define B_PCH_PCR_HDA_FNCFG_ADSPD BIT2
+#define B_PCH_PCR_HDA_FNCFG_HDASD BIT0
+#define R_PCH_PCR_HDA_CDCCFG (R_PCH_PCR_HDA_PCICDCCFG + 0x34)
+#define B_PCH_PCR_HDA_CDCCFG_DIS_SDIN2 BIT2
+
+//
+// Resides in Power Management & EBB Configuration Registers (600h)
+//
+#define R_PCH_PCR_HDA_PWRMANCFG 0x600 // Power Management & EBB Configuration Registers (PCR, offset 600h)
+#define R_PCH_PCR_HDA_APLLP0 (R_PCH_PCR_HDA_PWRMANCFG + 0x10)
+#define V_PCH_PCR_HDA_APLLP0 0xFC1E0000
+#define R_PCH_PCR_HDA_APLLP1 (R_PCH_PCR_HDA_PWRMANCFG + 0x14)
+#define V_PCH_PCR_HDA_APLLP1 0x00001E00
+#define R_PCH_PCR_HDA_APLLP2 (R_PCH_PCR_HDA_PWRMANCFG + 0x18)
+#define V_PCH_PCR_HDA_APLLP2 0x0000011D
+#define R_PCH_PCR_HDA_IOBCTL (R_PCH_PCR_HDA_PWRMANCFG + 0x1C)
+#define B_PCH_PCR_HDA_IOBCTL_OSEL (BIT9 | BIT8)
+#define V_PCH_PCR_HDA_IOBCTL_OSEL_HDALINK 0
+#define V_PCH_PCR_HDA_IOBCTL_OSEL_HDALINK_I2S 1
+#define V_PCH_PCR_HDA_IOBCTL_OSEL_I2S 3
+#define N_PCH_PCR_HDA_IOBCTL_OSEL 8
+#define B_PCH_PCR_HDA_IOBCTL_VSEL BIT1
+#define R_PCH_PCR_HDA_PTDC (R_PCH_PCR_HDA_PWRMANCFG + 0x28)
+#define B_PCH_PCR_HDA_PTDC_SRMIW (BIT6 | BIT5 | BIT4)
+#define V_PCH_PCR_HDA_PTDC_SRMIW_256XTAL 0x6
+#define N_PCH_PCR_HDA_PTDC_SRMIW 4
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h
new file mode 100644
index 0000000000..faa938e5a5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h
@@ -0,0 +1,185 @@
+/** @file
+ Register definition for HSIO
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_HSIO_H_
+#define _PCH_REGS_HSIO_H_
+
+#define B_PCH_HSIO_ACCESS_TYPE (BIT15 | BIT14)
+#define N_PCH_HSIO_ACCESS_TYPE 14
+#define V_PCH_HSIO_ACCESS_TYPE_BDCAST (BIT15 | BIT14)
+#define V_PCH_HSIO_ACCESS_TYPE_MULCAST BIT15
+#define B_PCH_HSIO_LANE_GROUP_NO (BIT13 | BIT12 | BIT11 | BIT10 | BIT9)
+#define B_PCH_HSIO_FUNCTION_NO (BIT8 | BIT7)
+#define N_PCH_HSIO_FUNCTION_NO 7
+#define B_PCH_HSIO_REG_OFFSET (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+#define V_PCH_HSIO_ACCESS_TYPE_BCAST 0x03
+#define V_PCH_HSIO_ACCESS_TYPE_MCAST 0x02
+#define V_PCH_HSIO_ACCESS_TYPE_UCAST 0x00
+
+#define V_PCH_HSIO_LANE_GROUP_NO_CMN_LANE 0x00
+
+#define V_PCH_HSIO_FUNCTION_NO_PCS 0x00
+#define V_PCH_HSIO_FUNCTION_NO_TX 0x01
+#define V_PCH_HSIO_FUNCTION_NO_RX 0x02
+
+#define V_PCH_HSIO_FUNCTION_NO_CMNDIG 0x00
+#define V_PCH_HSIO_FUNCTION_NO_CMNANA 0x01
+#define V_PCH_HSIO_FUNCTION_NO_PLL 0x02
+
+#define R_PCH_HSIO_PCS_DWORD0 0x0
+
+#define R_PCH_HSIO_PCS_DWORD1 0x4
+
+#define R_PCH_HSIO_PCS_DWORD4 0x10
+
+#define R_PCH_HSIO_PCS_DWORD8 0x20
+#define B_PCH_HSIO_PCS_DWORD8_CRI_RXEB_PTR_INIT_4_0 0x1F000000
+#define B_PCH_HSIO_PCS_DWORD8_CRI_RXEB_LOWATER_4_0 0x001F0000
+#define N_PCH_HSIO_PCS_DWORD8_CRI_RXEB_LOWATER_4_0 16
+#define B_PCH_HSIO_PCS_DWORD8_CRI_RXEB_HIWATER_4_0 0x00001F00
+#define N_PCH_HSIO_PCS_DWORD8_CRI_RXEB_HIWATER_4_0 8
+
+#define R_PCH_HSIO_PCS_DWORD9 0x24
+#define B_PCH_HSIO_PCS_DWORD9_REG_ENABLE_PWR_GATING BIT29
+
+#define R_PCH_HSIO_RX_DWORD8 0x120
+#define B_PCH_HSIO_RX_DWORD8_ICFGDFETAP3_EN BIT10
+
+#define R_PCH_HSIO_RX_DWORD9 0x124
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP4_OVERRIDE_EN BIT24
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP3_OVERRIDE_EN BIT26
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP2_OVERRIDE_EN BIT28
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP1_OVERRIDE_EN BIT30
+
+#define R_PCH_HSIO_RX_DWORD12 0x130
+#define B_PCH_HSIO_RX_DWORD12_O_CFGEWMARGINSEL BIT14
+
+#define R_PCH_HSIO_RX_DWORD15 0x13C
+
+#define R_PCH_HSIO_RX_DWORD20 0x150
+#define B_PCH_HSIO_RX_DWORD20_ICFGCTLEDATATAP_FULLRATE_5_0 (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24)
+#define N_PCH_HSIO_RX_DWORD20_ICFGCTLEDATATAP_FULLRATE_5_0 24
+
+#define R_PCH_HSIO_RX_DWORD21 0x154
+#define B_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_QUATRATE_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_QUATRATE_5_0 8
+#define B_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_HALFRATE_5_0 (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+#define N_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_HALFRATE_5_0 0
+
+#define R_PCH_HSIO_RX_DWORD23 0x15C
+#define B_PCH_HSIO_RX_DWORD23_ICFGVGABLWTAP_OVERRIDE_EN BIT2
+#define B_PCH_HSIO_RX_DWORD23_CFGVGATAP_ADAPT_OVERRIDE_EN BIT4
+
+#define R_PCH_HSIO_RX_DWORD25 0x164
+#define B_PCH_HSIO_RX_DWORD25_RX_TAP_CFG_CTRL BIT3
+#define B_PCH_HSIO_RX_DWORD25_CTLE_ADAPT_OFFSET_CFG_4_0 0x1F0000
+#define N_PCH_HSIO_RX_DWORD25_CTLE_ADAPT_OFFSET_CFG_4_0 16
+
+#define R_PCH_HSIO_RX_DWORD26 0x168
+#define B_PCH_HSIO_RX_DWORD26_SATA_EQ_DIS BIT16
+
+#define R_PCH_HSIO_RX_DWORD34 0x188
+#define B_PCH_HSIO_RX_DWORD34_MM_PH_OFC_SCALE_2_0 (BIT14 | BIT13 | BIT12)
+#define N_PCH_HSIO_RX_DWORD34_MM_PH_OFC_SCALE_2_0 12
+
+#define R_PCH_HSIO_RX_DWORD44 0x1B0
+#define B_PCH_HSIO_RX_DWORD44_0_DFE_DATASUMCAL0_7_0 0xFF0000
+#define N_PCH_HSIO_RX_DWORD44_0_DFE_DATASUMCAL0_7_0 16
+
+#define R_PCH_HSIO_RX_DWORD56 0x1E0
+#define B_PCH_HSIO_RX_DWORD56_ICFGPIDACCFGVALID BIT16
+
+#define R_PCH_HSIO_RX_DWORD57 0x1E4
+#define B_PCH_HSIO_RX_DWORD57_JIM_COURSE BIT30
+#define B_PCH_HSIO_RX_DWORD57_JIM_ENABLE BIT29
+#define B_PCH_HSIO_RX_DWORD57_JIMMODE BIT28
+#define B_PCH_HSIO_RX_DWORD57_JIMNUMCYCLES_3_0 0x0F000000
+#define N_PCH_HSIO_RX_DWORD57_JIMNUMCYCLES_3_0 24
+#define B_PCH_HSIO_RX_DWORD57_ICFGMARGINEN BIT0
+
+#define R_PCH_HSIO_RX_DWORD59 0x1EC
+#define R_PCH_HSIO_RX_DWORD60 0x1F0
+
+#define R_PCH_HSIO_TX_DWORD5 0x94
+#define B_PCH_HSIO_TX_DWORD5_OW2TAPGEN2DEEMPH3P5_5_0 (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_TX_DWORD5_OW2TAPGEN2DEEMPH3P5_5_0 16
+#define B_PCH_HSIO_TX_DWORD5_OW2TAPGEN1DEEMPH3P5_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_TX_DWORD5_OW2TAPGEN1DEEMPH3P5_5_0 8
+
+#define R_PCH_HSIO_TX_DWORD6 0x98
+#define B_PCH_HSIO_TX_DWORD6_OW2TAPGEN3DEEMPH6P0_5_0 (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_TX_DWORD6_OW2TAPGEN3DEEMPH6P0_5_0 16
+#define B_PCH_HSIO_TX_DWORD6_OW2TAPGEN2DEEMPH6P0_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_TX_DWORD6_OW2TAPGEN2DEEMPH6P0_5_0 8
+#define B_PCH_HSIO_TX_DWORD6_OW2TAPGEN1DEEMPH6P0_5_0 (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+#define R_PCH_HSIO_TX_DWORD8 0xA0
+#define B_PCH_HSIO_TX_DWORD8_ORATE10MARGIN_5_0 (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24)
+#define N_PCH_HSIO_TX_DWORD8_ORATE10MARGIN_5_0 24
+#define B_PCH_HSIO_TX_DWORD8_ORATE01MARGIN_5_0 (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_TX_DWORD8_ORATE01MARGIN_5_0 16
+#define B_PCH_HSIO_TX_DWORD8_ORATE00MARGIN_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_TX_DWORD8_ORATE00MARGIN_5_0 8
+
+#define R_PCH_HSIO_TX_DWORD19 0xCC
+
+#define R_PCH_HSIO_TX_DWORD23 0xDC
+
+#define R_PCH_LP_HSIO_LANE10_PCS_DWORD8 0x020
+#define R_PCH_LP_HSIO_LANE11_PCS_DWORD8 0x220
+#define R_PCH_LP_HSIO_LANE14_PCS_DWORD8 0x820
+#define R_PCH_LP_HSIO_LANE15_PCS_DWORD8 0xA20
+#define R_PCH_H_HSIO_LANE18_PCS_DWORD8 0x820
+#define R_PCH_H_HSIO_LANE19_PCS_DWORD8 0xA20
+#define R_PCH_H_HSIO_LANE22_PCS_DWORD8 0x020
+#define R_PCH_H_HSIO_LANE23_PCS_DWORD8 0x220
+#define R_PCH_H_HSIO_LANE24_PCS_DWORD8 0x420
+#define R_PCH_H_HSIO_LANE25_PCS_DWORD8 0x620
+#define R_PCH_H_HSIO_LANE26_PCS_DWORD8 0x820
+#define R_PCH_H_HSIO_LANE27_PCS_DWORD8 0xA20
+#define R_PCH_H_HSIO_LANE28_PCS_DWORD8 0xC20
+#define R_PCH_H_HSIO_LANE29_PCS_DWORD8 0xE20
+
+#define R_PCH_HSIO_CLANE0_CMN_ANA_DWORD2 0x8088
+#define B_PCH_HSIO_CLANE0_CMN_ANA_DWORD2_O_DTPLL1_lC_PLLEN_H_OVRDEN BIT5
+#define B_PCH_HSIO_CLANE0_CMN_ANA_DWORD2_O_DTPLL1_lC_FULLCALRESET_L_OVERDEN BIT3
+
+#define R_PCH_HSIO_PLL_SSC_DWORD2 0x8108
+#define B_PCH_HSIO_PLL_SSC_DWORD2_SSCSTEPSIZE_7_0 (BIT23 | BIT22 | BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_PLL_SSC_DWORD2_SSCSTEPSIZE_7_0 16
+#define B_PCH_HSIO_PLL_SSC_DWORD2_SSCSEN BIT10
+#define N_PCH_HSIO_PLL_SSC_DWORD2_SSCSEN 10
+
+#define R_PCH_HSIO_PLL_SSC_DWORD3 0x810C
+#define B_PCH_HSIO_PLL_SSC_DWORD3_SSC_PROPAGATE BIT0
+
+#define R_PCH_PCR_MODPHY0_COM0_CMN_DIG_DWORD12 0x8030
+#define B_PCH_PCR_MODPHY0_COM0_CMN_DIG_DWORD12_O_CFG_PWR_GATING_CTRL BIT0
+
+//
+// xHCI SSIC Private Configuration Register, but with opcode 4/5 for read/write access
+//
+#define R_PCH_PCR_MMP0_LANE_0_OFFSET 0x0
+#define R_PCH_PCR_MMP0_LANE_1_OFFSET 0x2000
+#define R_PCH_PCR_MMP0_IMPREG21 0x1050
+#define R_PCH_PCR_MMP0_IMPREG22 0x1054
+#define R_PCH_PCR_MMP0_IMPREG23 0x1058
+#define R_PCH_PCR_MMP0_IMPREG24 0x105C
+#define R_PCH_PCR_MMP0_IMPREG25 0x1060
+#define R_PCH_PCR_MMP0_CMNREG4 0xF00C
+#define R_PCH_PCR_MMP0_CMNREG15 0xF038
+#define R_PCH_PCR_MMP0_CMNREG16 0xF03C
+
+#endif //_PCH_REGS_HSIO_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h
new file mode 100644
index 0000000000..687a153f30
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h
@@ -0,0 +1,74 @@
+/** @file
+ Register names for PCH Integrated Sensor Hub (ISH3.0)
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_ISH_H_
+#define _PCH_REGS_ISH_H_
+
+//
+// ISH Controller Registers (D19:F0)
+//
+// PCI Configuration Space Registers
+#define PCI_DEVICE_NUMBER_PCH_ISH 19
+#define PCI_FUNCTION_NUMBER_PCH_ISH 0
+
+#define R_PCH_ISH_BAR0_LOW 0x10
+#define R_PCH_ISH_BAR0_HIGH 0x14
+#define V_PCH_ISH_BAR0_SIZE 0x100000
+#define N_PCH_ISH_BAR0_ALIGNMENT 20
+#define R_PCH_ISH_BAR1_LOW 0x18
+#define R_PCH_ISH_BAR1_HIGH 0x1C
+#define V_PCH_ISH_BAR1_SIZE 0x1000
+#define N_PCH_ISH_BAR1_ALIGNMENT 12
+
+//
+// ISH Private Configuration Space Registers (IOSF2OCP)
+// (PID:ISH)
+//
+#define R_PCH_PCR_ISH_PMCTL 0x1D0 ///< Power Management
+#define R_PCH_PCR_ISH_PCICFGCTRL 0x200 ///< PCI Configuration Control
+#define B_PCH_PCR_ISH_PCICFGCTR_PCI_IRQ 0x0FF00000 ///< PCI IRQ number
+#define N_PCH_PCR_ISH_PCICFGCTR_PCI_IRQ 20
+#define B_PCH_PCR_ISH_PCICFGCTR_ACPI_IRQ 0x000FF000 ///< ACPI IRQ number
+#define N_PCH_PCR_ISH_PCICFGCTR_ACPI_IRQ 12
+#define B_PCH_PCR_ISH_PCICFGCTR_IPIN1 (BIT11 | BIT10 | BIT9 | BIT8) ///< Interrupt Pin
+#define N_PCH_PCR_ISH_PCICFGCTR_IPIN1 8
+#define B_PCH_PCR_ISH_PCICFGCTRL_BAR1DIS BIT7 ///< BAR1 Disable
+
+//
+// Number of pins used by ISH controllers
+//
+#define PCH_ISH_PINS_PER_I2C_CONTROLLER 2
+#define PCH_ISH_PINS_PER_UART_CONTROLLER 4
+#define PCH_ISH_PINS_PER_SPI_CONTROLLER 4
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h
new file mode 100644
index 0000000000..21269155b5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h
@@ -0,0 +1,94 @@
+/** @file
+ Register names for ITSS
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_ITSS_H_
+#define _PCH_REGS_ITSS_H_
+
+//
+// ITSS PCRs (PID:ITSS)
+//
+#define R_PCH_PCR_ITSS_PIRQA_ROUT 0x3100 ///< PIRQA Routing Control register
+#define R_PCH_PCR_ITSS_PIRQB_ROUT 0x3101 ///< PIRQB Routing Control register
+#define R_PCH_PCR_ITSS_PIRQC_ROUT 0x3102 ///< PIRQC Routing Control register
+#define R_PCH_PCR_ITSS_PIRQD_ROUT 0x3103 ///< PIRQD Routing Control register
+#define R_PCH_PCR_ITSS_PIRQE_ROUT 0x3104 ///< PIRQE Routing Control register
+#define R_PCH_PCR_ITSS_PIRQF_ROUT 0x3105 ///< PIRQF Routing Control register
+#define R_PCH_PCR_ITSS_PIRQG_ROUT 0x3106 ///< PIRQG Routing Control register
+#define R_PCH_PCR_ITSS_PIRQH_ROUT 0x3107 ///< PIRQH Routing Control register
+#define B_PCH_PCR_ITSS_PIRQX_ROUT_REN 0x80 ///< Interrupt Routing Enable
+#define B_PCH_PCR_ITSS_PIRQX_ROUT_IR 0x0F ///< IRQ Routng
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_3 0x03 ///< Route PIRQx to IRQ3
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_4 0x04 ///< Route PIRQx to IRQ4
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_5 0x05 ///< Route PIRQx to IRQ5
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_6 0x06 ///< Route PIRQx to IRQ6
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_7 0x07 ///< Route PIRQx to IRQ7
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_9 0x09 ///< Route PIRQx to IRQ9
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_10 0x0A ///< Route PIRQx to IRQ10
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_11 0x0B ///< Route PIRQx to IRQ11
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_12 0x0C ///< Route PIRQx to IRQ12
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_14 0x0E ///< Route PIRQx to IRQ14
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_15 0x0F ///< Route PIRQx to IRQ15
+
+#define R_PCH_PCR_ITSS_PIR0 0x3140 ///< PCI Interrupt Route 0
+#define R_PCH_PCR_ITSS_PIR1 0x3142 ///< PCI Interrupt Route 1
+#define R_PCH_PCR_ITSS_PIR2 0x3144 ///< PCI Interrupt Route 2
+#define R_PCH_PCR_ITSS_PIR3 0x3146 ///< PCI Interrupt Route 3
+#define R_PCH_PCR_ITSS_PIR4 0x3148 ///< PCI Interrupt Route 4
+#define R_PCH_PCR_ITSS_PIR5 0x314A ///< PCI Interrupt Route 5
+#define R_PCH_PCR_ITSS_PIR6 0x314C ///< PCI Interrupt Route 6
+#define R_PCH_PCR_ITSS_PIR7 0x314E ///< PCI Interrupt Route 7
+#define R_PCH_PCR_ITSS_PIR8 0x3150 ///< PCI Interrupt Route 8
+#define R_PCH_PCR_ITSS_PIR9 0x3152 ///< PCI Interrupt Route 9
+#define R_PCH_PCR_ITSS_PIR10 0x3154 ///< PCI Interrupt Route 10
+#define R_PCH_PCR_ITSS_PIR11 0x3156 ///< PCI Interrupt Route 11
+#define R_PCH_PCR_ITSS_PIR12 0x3158 ///< PCI Interrupt Route 12
+
+#define R_PCH_PCR_ITSS_GIC 0x31FC ///< General Interrupt Control
+#define B_PCH_PCR_ITSS_GIC_MAX_IRQ_24 BIT9 ///< Max IRQ entry size, 1 = 24 entry size, 0 = 120 entry size
+#define B_PCH_PCR_ITSS_GIC_AME BIT17 ///< Alternate Access Mode Enable
+#define B_PCH_PCR_ITSS_GIC_SPS BIT16 ///< Shutdown Policy Select
+#define R_PCH_PCR_ITSS_IPC0 0x3200 ///< Interrupt Polarity Control 0
+#define R_PCH_PCR_ITSS_IPC1 0x3204 ///< Interrupt Polarity Control 1
+#define R_PCH_PCR_ITSS_IPC2 0x3208 ///< Interrupt Polarity Control 2
+#define R_PCH_PCR_ITSS_IPC3 0x320C ///< Interrupt Polarity Control 3
+#define R_PCH_PCR_ITSS_ITSSPRC 0x3300 ///< ITSS Power Reduction Control
+#define B_PCH_PCR_ITSS_ITSSPRC_PGCBDCGE BIT4 ///< PGCB Dynamic Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_HPETDCGE BIT3 ///< HPET Dynamic Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_8254CGE BIT2 ///< 8254 Static Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_IOSFICGE BIT1 ///< IOSF-Sideband Interface Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_ITSSCGE BIT0 ///< ITSS Clock Gate Enable
+
+#define R_PCH_PCR_ITSS_MMC 0x3334 ///< Master Message Control
+#define B_PCH_PCR_ITSS_MMC_MSTRMSG_EN BIT0 ///< Master Message Enable
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h
new file mode 100644
index 0000000000..bb4c2c15a9
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h
@@ -0,0 +1,148 @@
+/** @file
+ Register names for PCH LAN device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_LAN_H_
+#define _PCH_REGS_LAN_H_
+
+//
+// Gigabit LAN Controller configuration registers (D31:F6)
+//
+#define PCI_DEVICE_NUMBER_PCH_LAN 31
+#define PCI_FUNCTION_NUMBER_PCH_LAN 6
+
+#define R_PCH_LAN_MBARA 0x10
+#define B_PCH_LAN_MBARA_BA 0xFFFE0000
+#define N_PCH_LAN_MBARA_ALIGN 17
+#define R_PCH_LAN_LTR_CAP 0xA8
+#define R_PCH_LAN_CLIST1 0xC8
+#define B_PCH_LAN_CLIST1_NEXT 0xFF00
+#define B_PCH_LAN_CLIST1_CID 0x00FF
+#define R_PCH_LAN_PMC 0xCA
+#define B_PCH_LAN_PMC_PMES 0xF800
+#define B_PCH_LAN_PMC_D2S BIT10
+#define B_PCH_LAN_PMC_D1S BIT9
+#define B_PCH_LAN_PMC_AC (BIT8 | BIT7 | BIT6)
+#define B_PCH_LAN_PMC_DSI BIT5
+#define B_PCH_LAN_PMC_PMEC BIT3
+#define B_PCH_LAN_PMC_VS (BIT2 | BIT1 | BIT0)
+#define R_PCH_LAN_PMCS 0xCC
+#define B_PCH_LAN_PMCS_PMES BIT15
+#define B_PCH_LAN_PMCS_DSC (BIT14 | BIT13)
+#define B_PCH_LAN_PMCS_DSL 0x1E00
+#define V_PCH_LAN_PMCS_DSL0 0x0000
+#define V_PCH_LAN_PMCS_DSL3 0x0600
+#define V_PCH_LAN_PMCS_DSL4 0x0800
+#define V_PCH_LAN_PMCS_DSL7 0x0E00
+#define V_PCH_LAN_PMCS_DSL8 0x1000
+#define B_PCH_LAN_PMCS_PMEE BIT8
+#define B_PCH_LAN_PMCS_PS (BIT1 | BIT0)
+#define V_PCH_LAN_PMCS_PS0 0x00
+#define V_PCH_LAN_PMCS_PS3 0x03
+#define R_PCH_LAN_DR 0xCF
+#define B_PCH_LAN_DR 0xFF
+#define R_PCH_LAN_CLIST2 0xD0
+#define B_PCH_LAN_CLIST2_NEXT 0xFF00
+#define B_PCH_LAN_CLIST2_CID 0x00FF
+#define R_PCH_LAN_MCTL 0xD2
+#define B_PCH_LAN_MCTL_CID BIT7
+#define B_PCH_LAN_MCTL_MME (BIT6 | BIT5 | BIT4)
+#define B_PCH_LAN_MCTL_MMC (BIT3 | BIT2 | BIT1)
+#define B_PCH_LAN_MCTL_MSIE BIT0
+#define R_PCH_LAN_MADDL 0xD4
+#define B_PCH_LAN_MADDL 0xFFFFFFFF
+#define R_PCH_LAN_MADDH 0xD8
+#define B_PCH_LAN_MADDH 0xFFFFFFFF
+#define R_PCH_LAN_MDAT 0xDC
+#define B_PCH_LAN_MDAT 0xFFFFFFFF
+#define R_PCH_LAN_FLRCAP 0xE0
+#define B_PCH_LAN_FLRCAP_NEXT 0xFF00
+#define B_PCH_LAN_FLRCAP_CID 0x00FF
+#define V_PCH_LAN_FLRCAP_CID_SSEL0 0x13
+#define V_PCH_LAN_FLRCAP_CID_SSEL1 0x09
+#define R_PCH_LAN_FLRCLV 0xE2
+#define B_PCH_LAN_FLRCLV_FLRC_SSEL0 BIT9
+#define B_PCH_LAN_FLRCLV_TXP_SSEL0 BIT8
+#define B_PCH_LAN_FLRCLV_VSCID_SSEL1 0xF000
+#define B_PCH_LAN_FLRCLV_CAPVER_SSEL1 0x0F00
+#define B_PCH_LAN_FLRCLV_CAPLNG 0x00FF
+#define R_PCH_LAN_DEVCTRL 0xE4
+#define B_PCH_LAN_DEVCTRL BIT0
+#define R_PCH_LAN_CPCE 0x80
+#define B_PCH_LAN_CPCE_HAE BIT5
+#define B_PCH_LAN_CPCE_SE BIT3
+#define B_PCH_LAN_CPCE_D3HE BIT2
+#define B_PCH_LAN_CPCE_I3E BIT1
+#define B_PCH_LAN_CPCE_PCMCRE BIT0
+#define R_PCH_LAN_CD0I3 0x84
+#define B_PCH_LAN_CD0I3_RR BIT3
+#define B_PCH_LAN_CD0I3_D0I3 BIT2
+#define R_PCH_LAN_CLCTL 0x94
+#define R_PCH_LAN_LANDISCTRL 0xA0
+#define B_PCH_LAN_LANDISCTRL_DISABLE BIT0
+#define R_PCH_LAN_LOCKLANDIS 0xA4
+#define B_PCH_LAN_LOCKLANDIS_LOCK BIT0
+//
+// Gigabit LAN Capabilities and Status Registers (Memory space)
+//
+#define R_PCH_LAN_CSR_CTRL 0
+#define B_PCH_LAN_CSR_CTRL_MEHE BIT19
+#define R_PCH_LAN_CSR_STRAP 0x000C
+#define B_PCH_LAN_CSR_STRAP_NVM_VALID BIT11
+#define R_PCH_LAN_CSR_FEXTNVM6 0x0010
+#define R_PCH_LAN_CSR_CTRL_EXT 0x0018
+#define B_PCH_LAN_CSR_CTRL_EXT_FORCE_SMB BIT11
+#define R_PCH_LAN_CSR_MDIC 0x0020
+#define B_PCH_LAN_CSR_MDIC_RB BIT28
+#define B_PCH_LAN_CSR_MDIC_DATA 0xFFFF
+#define R_PCH_LAN_CSR_FEXT 0x002C
+#define B_PCH_LAN_CSR_FEXT_WOL BIT30
+#define B_PCH_LAN_CSR_FEXT_WOL_VALID BIT31
+#define R_PCH_LAN_CSR_EXTCNF_CTRL 0x0F00
+#define B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG BIT5
+#define B_PCH_LAN_CSR_EXTCNF_K1OFF_EN BIT8
+#define R_PCH_LAN_CSR_PHY_CTRL 0x0F10
+#define B_PCH_LAN_CSR_PHY_CTRL_GGD BIT6
+#define B_PCH_LAN_CSR_PHY_CTRL_GBEDIS BIT3
+#define B_PCH_LAN_CSR_PHY_CTRL_LPLUND BIT2
+#define B_PCH_LAN_CSR_PHY_CTRL_LPLUD BIT1
+#define R_PCH_LAN_CSR_F18 0x0F18
+#define B_PCH_LAN_CSR_F18_K1OFF_EN BIT31
+#define R_PCH_LAN_CSR_PBECCSTS 0x100C
+#define B_PCH_LAN_CSR_PBECCSTS_ECC_EN BIT16
+#define R_PCH_LAN_CSR_RAL 0x5400
+#define R_PCH_LAN_CSR_RAH 0x5404
+#define B_PCH_LAN_CSR_RAH_RAH 0x0000FFFF
+#define R_PCH_LAN_CSR_WUC 0x5800
+#define B_PCH_LAN_CSR_WUC_APME BIT0
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h
new file mode 100644
index 0000000000..7c6f639260
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h
@@ -0,0 +1,610 @@
+/** @file
+ Register names for PCH LPC/eSPI device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_LPC_H_
+#define _PCH_REGS_LPC_H_
+
+//
+// PCI to LPC Bridge Registers (D31:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define PCI_FUNCTION_NUMBER_PCH_LPC 0
+
+typedef enum {
+ PchHB0 = 0x01,
+ PchHC0,
+ PchHD0,
+ PchHD1,
+ PchLpB0 = 0x23,
+ PchLpB1,
+ PchLpC0,
+ PchLpC1,
+ KblPchHA0 = 0x40,
+ PchSteppingMax
+} PCH_STEPPING;
+
+#define SKL_PCH_H_MIN_SUPPORTED_STEPPING PchHB0
+#define KBL_PCH_H_MIN_SUPPORTED_STEPPING KblPchHA0
+#define PCH_LP_MIN_SUPPORTED_STEPPING PchLpB0
+
+#define V_PCH_LPC_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+
+//
+//
+// SKL PCH Server/WS LPC Device IDs
+//
+#define V_SKL_PCH_H_LPC_DEVICE_ID_SVR_0 0xA149 ///< Server SKU Intel C236 Chipset
+#define V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1 0xA14A ///< Server SKU Intel C232 Chipset
+#define V_SKL_PCH_H_LPC_DEVICE_ID_SVR_2 0xA150 ///< Server SKU Intel CM236 Chipset
+#define V_SKL_PCH_H_LPC_DEVICE_ID_A14B 0xA14B ///< Super SKU Unlocked
+
+//
+// SKL PCH-H Desktop LPC Device IDs
+//
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU 0xA141 ///< PCH H Desktop Super SKU unlocked
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_0 0xA142 ///< PCH H Desktop Super SKU locked
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_1 0xA143 ///< PCH H Desktop H110
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_2 0xA144 ///< PCH H Desktop H170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_3 0xA145 ///< PCH H Desktop Z170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_4 0xA146 ///< PCH H Desktop Q170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_5 0xA147 ///< PCH H Desktop Q150
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_6 0xA148 ///< PCH H Desktop B150
+//
+// SKL PCH-H Mobile LPC Device IDs
+//
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU 0xA141 ///< PCH H Mobile Super SKU unlocked
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_0 0xA14D ///< PCH H Mobile QM170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_1 0xA14E ///< PCH H Mobile HM170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_3 0xA151 ///< PCH H Mobile QMS180 (SFF)
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_4 0xA152 ///< KBL PCH H Mobile HM175
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_5 0xA153 ///< KBL PCH H Mobile QM175
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_6 0xA154 ///< KBL PCH H Mobile CM238
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_8 0xA156 ///< KBL PCH H Mobile QMS185 (SFF)
+
+//
+// SKL PCH-LP LPC Device IDs
+//
+#define V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU 0x9D41 ///< PCH LP Mobile Super SKU unlocked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_0 0x9D42 ///< PCH LP Mobile Super SKU locked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_1 0x9D43 ///< PCH LP Mobile (U) Base SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_2 0x9D46 ///< PCH LP Mobile (Y) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_3 0x9D48 ///< PCH LP Mobile (U) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU_1 0x9D51 ///< KBL PCH LP Mobile Super SKU unlocked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_4 0x9D52 ///< KBL PCH LP Mobile Super SKU locked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_5 0x9D53 ///< KBL PCH LP Mobile (U) Base SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_6 0x9D56 ///< KBL PCH LP Mobile (Y) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_7 0x9D58 ///< KBL PCH LP Mobile (U) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_8 0x9D4B ///< KBL PCH LP Mobile (Y) iHDCP 2.2 Premium
+#define V_PCH_LP_LPC_DEVICE_ID_MB_9 0x9D4E ///< KBL PCH LP Mobile (U) iHDCP 2.2 Premium
+#define V_PCH_LP_LPC_DEVICE_ID_MB_10 0x9D50 ///< KBL PCH LP Mobile (U) iHDCP 2.2 Base
+
+
+
+//
+// KBL PCH Server/WS LPC Device IDs
+//
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU 0xA2D0 ///< ES Super SKU Unlocked. This is SKL-PCH-H in KBL-PCH-H package
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_SUPER_SKU 0xA2D1 ///< Super SKU Unlocked
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_0 0xA2D2 ///< Server SKU X290
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_1 0xA2D3 ///< Server SKU C6xx
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_2 0xA2CE ///< Server SKU ES SuperSKU Server
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_3 0xA2CF ///< Server SKU SuperSKU Server
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_4 0xA2D4 ///< Server SKU C422B
+
+
+//
+// KBL PCH-H Desktop LPC Device IDs
+//
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU 0xA2C0 ///< PCH H Desktop ES Super SKU unlocked. This is SKL-PCH-H in KBL-PCH-H package
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU 0xA2C1 ///< PCH H Desktop Super SKU unlocked
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_H270 0xA2C4 ///< PCH H Desktop H270
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z270 0xA2C5 ///< PCH H Desktop Z270
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q270 0xA2C6 ///< PCH H Desktop Q270
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250 0xA2C7 ///< PCH H Desktop Q250
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250 0xA2C8 ///< PCH H Desktop B250
+
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_H215 0xA2C3 ///< PCH H Desktop H215
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z370 0xA2C9 ///< PCH H Desktop Z370
+
+#define V_PCH_LPC_RID_0 0x00
+#define V_PCH_LPC_RID_1 0x01
+#define V_PCH_LPC_RID_9 0x09
+#define V_PCH_LPC_RID_10 0x10
+#define V_PCH_LPC_RID_11 0x11
+#define V_PCH_LPC_RID_20 0x20
+#define V_PCH_LPC_RID_21 0x21
+#define V_PCH_LPC_RID_30 0x30
+#define V_PCH_LPC_RID_31 0x31
+#define R_PCH_LPC_SERIRQ_CNT 0x64
+#define B_PCH_LPC_SERIRQ_CNT_SIRQEN 0x80
+#define B_PCH_LPC_SERIRQ_CNT_SIRQMD 0x40
+#define B_PCH_LPC_SERIRQ_CNT_SIRQSZ 0x3C
+#define N_PCH_LPC_SERIRQ_CNT_SIRQSZ 2
+#define B_PCH_LPC_SERIRQ_CNT_SFPW 0x03
+#define N_PCH_LPC_SERIRQ_CNT_SFPW 0
+#define V_PCH_LPC_SERIRQ_CNT_SFPW_4CLK 0x00
+#define V_PCH_LPC_SERIRQ_CNT_SFPW_6CLK 0x01
+#define V_PCH_LPC_SERIRQ_CNT_SFPW_8CLK 0x02
+#define R_PCH_LPC_IOD 0x80
+#define B_PCH_LPC_IOD_FDD 0x1000
+#define N_PCH_LPC_IOD_FDD 12
+#define V_PCH_LPC_IOD_FDD_3F0 0
+#define V_PCH_LPC_IOD_FDD_370 1
+#define B_PCH_LPC_IOD_LPT 0x0300
+#define N_PCH_LPC_IOD_LPT 8
+#define V_PCH_LPC_IOD_LPT_378 0
+#define V_PCH_LPC_IOD_LPT_278 1
+#define V_PCH_LPC_IOD_LPT_3BC 2
+#define B_PCH_LPC_IOD_COMB 0x0070
+#define N_PCH_LPC_IOD_COMB 4
+#define V_PCH_LPC_IOD_COMB_3F8 0
+#define V_PCH_LPC_IOD_COMB_2F8 1
+#define V_PCH_LPC_IOD_COMB_220 2
+#define V_PCH_LPC_IOD_COMB_228 3
+#define V_PCH_LPC_IOD_COMB_238 4
+#define V_PCH_LPC_IOD_COMB_2E8 5
+#define V_PCH_LPC_IOD_COMB_338 6
+#define V_PCH_LPC_IOD_COMB_3E8 7
+#define B_PCH_LPC_IOD_COMA 0x0007
+#define N_PCH_LPC_IOD_COMA 0
+#define V_PCH_LPC_IOD_COMA_3F8 0
+#define V_PCH_LPC_IOD_COMA_2F8 1
+#define V_PCH_LPC_IOD_COMA_220 2
+#define V_PCH_LPC_IOD_COMA_228 3
+#define V_PCH_LPC_IOD_COMA_238 4
+#define V_PCH_LPC_IOD_COMA_2E8 5
+#define V_PCH_LPC_IOD_COMA_338 6
+#define V_PCH_LPC_IOD_COMA_3E8 7
+#define R_PCH_LPC_IOE 0x82
+#define B_PCH_LPC_IOE_ME2 BIT13 ///< Microcontroller Enable #2, Enables decoding of I/O locations 4Eh and 4Fh to LPC
+#define B_PCH_LPC_IOE_SE BIT12 ///< Super I/O Enable, Enables decoding of I/O locations 2Eh and 2Fh to LPC.
+#define B_PCH_LPC_IOE_ME1 BIT11 ///< Microcontroller Enable #1, Enables decoding of I/O locations 62h and 66h to LPC.
+#define B_PCH_LPC_IOE_KE BIT10 ///< Keyboard Enable, Enables decoding of the keyboard I/O locations 60h and 64h to LPC.
+#define B_PCH_LPC_IOE_HGE BIT9 ///< High Gameport Enable, Enables decoding of the I/O locations 208h to 20Fh to LPC.
+#define B_PCH_LPC_IOE_LGE BIT8 ///< Low Gameport Enable, Enables decoding of the I/O locations 200h to 207h to LPC.
+#define B_PCH_LPC_IOE_FDE BIT3 ///< Floppy Drive Enable, Enables decoding of the FDD range to LPC. Range is selected by LIOD.FDE
+#define B_PCH_LPC_IOE_PPE BIT2 ///< Parallel Port Enable, Enables decoding of the LPT range to LPC. Range is selected by LIOD.LPT.
+#define B_PCH_LPC_IOE_CBE BIT1 ///< Com Port B Enable, Enables decoding of the COMB range to LPC. Range is selected LIOD.CB.
+#define B_PCH_LPC_IOE_CAE BIT0 ///< Com Port A Enable, Enables decoding of the COMA range to LPC. Range is selected LIOD.CA.
+#define R_PCH_LPC_GEN1_DEC 0x84
+#define R_PCH_LPC_GEN2_DEC 0x88
+#define R_PCH_LPC_GEN3_DEC 0x8C
+#define R_PCH_LPC_GEN4_DEC 0x90
+#define B_PCH_LPC_GENX_DEC_IODRA 0x00FC0000
+#define B_PCH_LPC_GENX_DEC_IOBAR 0x0000FFFC
+#define B_PCH_LPC_GENX_DEC_EN 0x00000001
+#define R_PCH_LPC_ULKMC 0x94
+#define B_PCH_LPC_ULKMC_SMIBYENDPS BIT15
+#define B_PCH_LPC_ULKMC_TRAPBY64W BIT11
+#define B_PCH_LPC_ULKMC_TRAPBY64R BIT10
+#define B_PCH_LPC_ULKMC_TRAPBY60W BIT9
+#define B_PCH_LPC_ULKMC_TRAPBY60R BIT8
+#define B_PCH_LPC_ULKMC_SMIATENDPS BIT7
+#define B_PCH_LPC_ULKMC_PSTATE BIT6
+#define B_PCH_LPC_ULKMC_A20PASSEN BIT5
+#define B_PCH_LPC_ULKMC_USBSMIEN BIT4
+#define B_PCH_LPC_ULKMC_64WEN BIT3
+#define B_PCH_LPC_ULKMC_64REN BIT2
+#define B_PCH_LPC_ULKMC_60WEN BIT1
+#define B_PCH_LPC_ULKMC_60REN BIT0
+#define R_PCH_LPC_LGMR 0x98
+#define B_PCH_LPC_LGMR_MA 0xFFFF0000
+#define B_PCH_LPC_LGMR_LMRD_EN BIT0
+
+#define R_PCH_LPC_FWH_BIOS_SEL 0xD0
+#define B_PCH_LPC_FWH_BIOS_SEL_F8 0xF0000000
+#define B_PCH_LPC_FWH_BIOS_SEL_F0 0x0F000000
+#define B_PCH_LPC_FWH_BIOS_SEL_E8 0x00F00000
+#define B_PCH_LPC_FWH_BIOS_SEL_E0 0x000F0000
+#define B_PCH_LPC_FWH_BIOS_SEL_D8 0x0000F000
+#define B_PCH_LPC_FWH_BIOS_SEL_D0 0x00000F00
+#define B_PCH_LPC_FWH_BIOS_SEL_C8 0x000000F0
+#define B_PCH_LPC_FWH_BIOS_SEL_C0 0x0000000F
+#define R_PCH_LPC_FWH_BIOS_SEL2 0xD4
+#define B_PCH_LPC_FWH_BIOS_SEL2_70 0xF000
+#define B_PCH_LPC_FWH_BIOS_SEL2_60 0x0F00
+#define B_PCH_LPC_FWH_BIOS_SEL2_50 0x00F0
+#define B_PCH_LPC_FWH_BIOS_SEL2_40 0x000F
+#define R_PCH_LPC_BDE 0xD8 ///< BIOS decode enable
+#define B_PCH_LPC_BDE_F8 0x8000
+#define B_PCH_LPC_BDE_F0 0x4000
+#define B_PCH_LPC_BDE_E8 0x2000
+#define B_PCH_LPC_BDE_E0 0x1000
+#define B_PCH_LPC_BDE_D8 0x0800
+#define B_PCH_LPC_BDE_D0 0x0400
+#define B_PCH_LPC_BDE_C8 0x0200
+#define B_PCH_LPC_BDE_C0 0x0100
+#define B_PCH_LPC_BDE_LEG_F 0x0080
+#define B_PCH_LPC_BDE_LEG_E 0x0040
+#define B_PCH_LPC_BDE_70 0x0008
+#define B_PCH_LPC_BDE_60 0x0004
+#define B_PCH_LPC_BDE_50 0x0002
+#define B_PCH_LPC_BDE_40 0x0001
+#define R_PCH_LPC_PCC 0xE0
+#define B_PCH_LPC_PCC_CLKRUN_EN 0x0001
+#define B_PCH_LPC_FVEC0_USB_PORT_CAP 0x00000C00
+#define V_PCH_LPC_FVEC0_USB_14_PORT 0x00000000
+#define V_PCH_LPC_FVEC0_USB_12_PORT 0x00000400
+#define V_PCH_LPC_FVEC0_USB_10_PORT 0x00000800
+#define B_PCH_LPC_FVEC0_SATA_RAID_CAP 0x00000080
+#define B_PCH_LPC_FVEC0_SATA_PORT23_CAP 0x00000040
+#define B_PCH_LPC_FVEC0_SATA_PORT1_6GB_CAP 0x00000008
+#define B_PCH_LPC_FVEC0_SATA_PORT0_6GB_CAP 0x00000004
+#define B_PCH_LPC_FVEC0_PCI_CAP 0x00000002
+#define R_PCH_LPC_FVEC1 0x01
+#define B_PCH_LPC_FVEC1_USB_R_CAP 0x00400000
+#define R_PCH_LPC_FVEC2 0x02
+#define V_PCH_LPC_FVEC2_PCIE_PORT78_CAP 0x00200000
+#define V_PCH_LPC_FVEC2_PCH_IG_SUPPORT_CAP 0x00020000 ///< PCH Integrated Graphics Support Capability
+#define R_PCH_LPC_FVEC3 0x03
+#define B_PCH_LPC_FVEC3_DCMI_CAP 0x00002000 ///< Data Center Manageability Interface (DCMI) Capability
+#define B_PCH_LPC_FVEC3_NM_CAP 0x00001000 ///< Node Manager Capability
+
+#define R_PCH_LPC_MDAP 0xC0
+#define B_PCH_LPC_MDAP_POLICY_EN BIT31
+#define B_PCH_LPC_MDAP_PDMA_EN BIT30
+#define B_PCH_LPC_MDAP_VALUE 0x0001FFFF
+
+//
+// APM Registers
+//
+#define R_PCH_APM_CNT 0xB2
+#define R_PCH_APM_STS 0xB3
+
+#define R_PCH_LPC_BC 0xDC ///< Bios Control
+#define S_PCH_LPC_BC 1
+#define B_PCH_LPC_BC_BILD BIT7 ///< BIOS Interface Lock-Down
+#define B_PCH_LPC_BC_BBS BIT6 ///< Boot BIOS strap
+#define N_PCH_LPC_BC_BBS 6
+#define V_PCH_LPC_BC_BBS_SPI 0 ///< Boot BIOS strapped to SPI
+#define V_PCH_LPC_BC_BBS_LPC 1 ///< Boot BIOS strapped to LPC
+#define B_PCH_LPC_BC_EISS BIT5 ///< Enable InSMM.STS
+#define B_PCH_LPC_BC_TS BIT4 ///< Top Swap
+#define B_PCH_LPC_BC_LE BIT1 ///< Lock Enable
+#define N_PCH_LPC_BC_LE 1
+#define B_PCH_LPC_BC_WPD BIT0 ///< Write Protect Disable
+
+#define R_PCH_ESPI_PCBC 0xDC ///< Peripheral Channel BIOS Control
+#define S_PCH_ESPI_PCBC 4 ///< Peripheral Channel BIOS Control register size
+#define B_PCH_ESPI_PCBC_BWRE BIT11 ///< BIOS Write Report Enable
+#define N_PCH_ESPI_PCBC_BWRE 11 ///< BIOS Write Report Enable bit position
+#define B_PCH_ESPI_PCBC_BWRS BIT10 ///< BIOS Write Report Status
+#define N_PCH_ESPI_PCBC_BWRS 10 ///< BIOS Write Report Status bit position
+#define B_PCH_ESPI_PCBC_BWPDS BIT8 ///< BIOS Write Protect Disable Status
+#define N_PCH_ESPI_PCBC_BWPDS 8 ///< BIOS Write Protect Disable Status bit position
+#define B_PCH_ESPI_PCBC_ESPI_EN BIT2 ///< eSPI Enable Pin Strap
+#define B_PCH_ESPI_PCBC_LE BIT1 ///< Lock Enable
+#define N_PCH_ESPI_PCBC_LE 1
+
+//
+// eSPI slave registers
+//
+#define R_ESPI_SLAVE_CHA_0_CAP_AND_CONF 0x10 ///< Channel 0 Capabilities and Configurations
+#define B_ESPI_SLAVE_CHA_0_CAP_AND_CONF_BME BIT2 ///< Bus Master Enable
+
+//
+// Processor interface registers
+//
+#define R_PCH_NMI_SC 0x61
+#define B_PCH_NMI_SC_SERR_NMI_STS BIT7
+#define B_PCH_NMI_SC_IOCHK_NMI_STS BIT6
+#define B_PCH_NMI_SC_TMR2_OUT_STS BIT5
+#define B_PCH_NMI_SC_REF_TOGGLE BIT4
+#define B_PCH_NMI_SC_IOCHK_NMI_EN BIT3
+#define B_PCH_NMI_SC_PCI_SERR_EN BIT2
+#define B_PCH_NMI_SC_SPKR_DAT_EN BIT1
+#define B_PCH_NMI_SC_TIM_CNT2_EN BIT0
+#define R_PCH_NMI_EN 0x70
+#define B_PCH_NMI_EN_NMI_EN BIT7
+
+//
+// Reset Generator I/O Port
+//
+#define R_PCH_RST_CNT 0xCF9
+#define B_PCH_RST_CNT_FULL_RST BIT3
+#define B_PCH_RST_CNT_RST_CPU BIT2
+#define B_PCH_RST_CNT_SYS_RST BIT1
+#define V_PCH_RST_CNT_FULLRESET 0x0E
+#define V_PCH_RST_CNT_HARDRESET 0x06
+#define V_PCH_RST_CNT_SOFTRESET 0x04
+#define V_PCH_RST_CNT_HARDSTARTSTATE 0x02
+#define V_PCH_RST_CNT_SOFTSTARTSTATE 0x00
+
+//
+// RTC register
+//
+#define R_PCH_RTC_INDEX 0x70
+#define R_PCH_RTC_TARGET 0x71
+#define R_PCH_RTC_EXT_INDEX 0x72
+#define R_PCH_RTC_EXT_TARGET 0x73
+#define R_PCH_RTC_INDEX_ALT 0x74
+#define R_PCH_RTC_TARGET_ALT 0x75
+#define R_PCH_RTC_EXT_INDEX_ALT 0x76
+#define R_PCH_RTC_EXT_TARGET_ALT 0x77
+#define R_PCH_RTC_REGA 0x0A
+#define B_PCH_RTC_REGA_UIP 0x80
+#define R_PCH_RTC_REGB 0x0B
+#define B_PCH_RTC_REGB_SET 0x80
+#define B_PCH_RTC_REGB_PIE 0x40
+#define B_PCH_RTC_REGB_AIE 0x20
+#define B_PCH_RTC_REGB_UIE 0x10
+#define B_PCH_RTC_REGB_DM 0x04
+#define B_PCH_RTC_REGB_HOURFORM 0x02
+#define R_PCH_RTC_REGC 0x0C
+#define R_PCH_RTC_REGD 0x0D
+
+//
+// Private Configuration Register
+// RTC PCRs (PID:RTC)
+//
+#define R_PCH_PCR_RTC_CONF 0x3400 ///< RTC Configuration register
+#define S_PCH_PCR_RTC_CONF 4
+#define B_PCH_PCR_RTC_CONF_UCMOS_LOCK BIT4
+#define B_PCH_PCR_RTC_CONF_LCMOS_LOCK BIT3
+#define B_PCH_PCR_RTC_CONF_RESERVED BIT31
+#define B_PCH_PCR_RTC_CONF_UCMOS_EN BIT2 ///< Upper CMOS bank enable
+#define R_PCH_PCR_RTC_BUC 0x3414 ///< Backed Up Control
+#define B_PCH_PCR_RTC_BUC_TS BIT0 ///< Top Swap
+#define R_PCH_PCR_RTC_RTCDCG 0x3418 ///< RTC Dynamic Clock Gating Control
+#define R_PCH_PCR_RTC_RTCDCG_RTCPCICLKDCGEN BIT1 ///< ipciclk_clk (24 MHz) Dynamic Clock Gate Enable
+#define R_PCH_PCR_RTC_RTCDCG_RTCROSIDEDCGEN BIT0 ///< rosc_side_clk (120 MHz) Dynamic Clock Gate Enable
+#define R_PCH_PCR_RTC_3F00 0x3F00
+#define R_PCH_PCR_RTC_UIPSMI 0x3F04 ///< RTC Update In Progress SMI Control
+
+//
+// LPC PCR Registers
+//
+#define R_PCH_PCR_LPC_HVMTCTL 0x3410
+#define R_PCH_PCR_LPC_GCFD 0x3418
+#define R_PCH_PCR_LPC_PRC 0x341C
+#define R_PCH_PCR_LPC_PCT 0x3420
+#define R_PCH_PCR_LPC_SCT 0x3424
+#define R_PCH_PCR_LPC_LPCCT 0x3428
+#define R_PCH_PCR_LPC_ULTOR 0x3500
+
+//
+// eSPI PCR Registers
+//
+#define R_PCH_PCR_ESPI_SLV_CFG_REG_CTL 0x4000 ///< Slave Configuration Register and Link Control
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRE BIT31 ///< Slave Configuration Register Access Enable
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRS (BIT30 | BIT29 | BIT28) ///< Slave Configuration Register Access Status
+#define N_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRS 28 ///< Slave Configuration Register Access Status bit position
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SBLCL BIT27 ///< IOSF-SB eSPI Link Configuration Lock
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRS_NOERR 7 ///< No errors (transaction completed successfully)
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SID (BIT20 | BIT19) ///< Slave ID
+#define N_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SID 19 ///< Slave ID bit position
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT (BIT17 | BIT16) ///< Slave Configuration Register Access Type
+#define N_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT 16 ///< Slave Configuration Register Access Type bit position
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_RD 0 ///< Slave Configuration register read from address SCRA[11:0]
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_WR 1 ///< Slave Configuration register write to address SCRA[11:0]
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_STS 2 ///< Slave Status register read
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_RS 3 ///< In-Band reset
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRA 0x00000FFF ///< Slave Configuration Register Address
+#define R_PCH_PCR_ESPI_SLV_CFG_REG_DATA 0x4004 ///< Slave Configuration Register Data
+
+#define R_PCH_PCR_ESPI_PCERR_SLV0 0x4020 ///< Peripheral Channel Error for Slave 0
+#define R_PCH_PCR_ESPI_PCERR_SLV1 0x4024 ///< Peripheral Channel Error for Slave 1
+#define R_PCH_PCR_ESPI_VWERR_SLV0 0x4030 ///< Virtual Wire Channel Error for Slave 0
+#define R_PCH_PCR_ESPI_VWERR_SLV1 0x4034 ///< Virtual Wire Channel Error for Slave 1
+#define R_PCH_PCR_ESPI_FCERR_SLV0 0x4040 ///< Flash Access Channel Error for Slave 0
+#define B_PCH_PCR_ESPI_XERR_XNFEE (BIT14 | BIT13) ///< Non-Fatal Error Reporting Enable bits
+#define N_PCH_PCR_ESPI_XERR_XNFEE 13 ///< Non-Fatal Error Reporting Enable bit position
+#define V_PCH_PCR_ESPI_XERR_XNFEE_SMI 3 ///< Enable Non-Fatal Error Reporting as SMI
+#define B_PCH_PCR_ESPI_XERR_XNFES BIT12 ///< Fatal Error Status
+#define B_PCH_PCR_ESPI_XERR_XFEE (BIT6 | BIT5) ///< Fatal Error Reporting Enable bits
+#define N_PCH_PCR_ESPI_XERR_XFEE 5 ///< Fatal Error Reporting Enable bit position
+#define V_PCH_PCR_ESPI_XERR_XFEE_SMI 3 ///< Enable Fatal Error Reporting as SMI
+#define B_PCH_PCR_ESPI_XERR_XFES BIT4 ///< Fatal Error Status
+#define B_PCH_PCR_ESPI_PCERR_SLV0_PCURD BIT24 ///< Peripheral Channel Unsupported Request Detected
+#define R_PCH_PCR_ESPI_LNKERR_SLV0 0x4050 ///< Link Error for Slave 0
+#define S_PCH_PCR_ESPI_LNKERR_SLV0 4 ///< Link Error for Slave 0 register size
+#define B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR BIT31 ///< eSPI Link and Slave Channel Recovery Required
+#define B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E (BIT22 | BIT21) ///< Fatal Error Type 1 Reporting Enable
+#define N_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E 21 ///< Fatal Error Type 1 Reporting Enable bit position
+#define V_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E_SMI 3 ///< Enable Fatal Error Type 1 Reporting as SMI
+#define B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S BIT20 ///< Link Fatal Error Type 1 Status
+#define R_PCH_PCR_ESPI_CFG_VAL 0xC00C ///< ESPI Enabled Strap
+#define B_PCH_PCR_ESPI_ENABLE_STRAP BIT0 ///< ESPI Enabled Strap bit position
+
+
+
+//
+// LPC Device ID macros
+//
+//
+// Device IDs that are SKL PCH-H Desktop specific
+//
+#define IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_0) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_1) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_2) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_3) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_4) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_5) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_6) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU /* SKL-PCH-H in KBL-PCH-H package */) \
+ )
+
+//
+// Device IDs that are KBL PCH-H Desktop specific
+//
+#define IS_KBL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_H215) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z370) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_H270) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z270) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q270) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250) \
+ )
+
+//
+// Device IDs that are PCH-H Desktop specific
+//
+#define IS_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ )
+
+//
+// Device IDs that are PCH-H Mobile specific
+//
+
+#define IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_0) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_1) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_3) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_4) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_5) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_6) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_8) \
+ )
+
+//
+// Device IDs that are PCH-LP Mobile specific
+//
+#define IS_PCH_LP_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ ( \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_0) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_1) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_2) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_3) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU_1) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_4) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_5) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_6) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_7) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_8) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_9) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_10) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_PCH_LP_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ )
+
+//
+// Device IDS that are SKL PCH Server\Workstation specific
+//
+#define IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_SVR_0) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_SVR_2) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_A14B) \
+ )
+
+//
+// Device IDS that are KBL PCH Server\Workstation specific
+//
+#define IS_KBL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_SUPER_SKU) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_0) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_1) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_2) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_3) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_4) \
+ )
+
+
+#define IS_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) || \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_SKL_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_KBL_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) || \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ )
+
+#define IS_PCH_LP_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_LP_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_LPC_DEVICE_ID(DeviceId) \
+ )
+
+#define IS_SKL_PCH_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_PCH_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_KBL_PCH_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_KBL_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ )
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h
new file mode 100644
index 0000000000..b2779ab0ce
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h
@@ -0,0 +1,138 @@
+/** @file
+ Register names for PCH P2SB device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_P2SB_H_
+#define _PCH_REGS_P2SB_H_
+
+//
+// PCI to P2SB Bridge Registers (D31:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_P2SB 31
+#define PCI_FUNCTION_NUMBER_PCH_P2SB 1
+
+#define V_PCH_P2SB_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define R_PCH_P2SB_SBREG_BAR 0x10
+#define B_PCH_P2SB_SBREG_RBA 0xFF000000
+#define R_PCH_P2SB_SBREG_BARH 0x14
+#define B_PCH_P2SB_SBREG_RBAH 0xFFFFFFFF
+#define R_PCH_P2SB_VBDF 0x50
+#define B_PCH_P2SB_VBDF_BUF 0xFF00
+#define B_PCH_P2SB_VBDF_DEV 0x00F8
+#define B_PCH_P2SB_VBDF_FUNC 0x0007
+#define R_PCH_P2SB_ESMBDF 0x52
+#define B_PCH_P2SB_ESMBDF_BUF 0xFF00
+#define B_PCH_P2SB_ESMBDF_DEV 0x00F8
+#define B_PCH_P2SB_ESMBDF_FUNC 0x0007
+#define R_PCH_P2SB_RCFG 0x54
+#define B_PCH_P2SB_RCFG_RPRID 0x0000FF00
+#define B_PCH_P2SB_RCFG_RSE BIT0
+#define R_PCH_P2SB_HPTC 0x60
+#define B_PCH_P2SB_HPTC_AE BIT7
+#define B_PCH_P2SB_HPTC_AS 0x0003
+#define N_PCH_HPET_ADDR_ASEL 12
+#define V_PCH_HPET_BASE0 0xFED00000
+#define V_PCH_HPET_BASE1 0xFED01000
+#define V_PCH_HPET_BASE2 0xFED02000
+#define V_PCH_HPET_BASE3 0xFED03000
+#define R_PCH_P2SB_IOAC 0x64
+#define B_PCH_P2SB_IOAC_AE BIT8
+#define B_PCH_P2SB_IOAC_ASEL 0x00FF
+#define N_PCH_IO_APIC_ASEL 12
+#define R_PCH_IO_APIC_INDEX 0xFEC00000
+#define R_PCH_IO_APIC_DATA 0xFEC00010
+#define R_PCH_IO_APIC_EOI 0xFEC00040
+#define R_PCH_P2SB_IBDF 0x6C
+#define B_PCH_P2SB_IBDF_BUF 0xFF00
+#define B_PCH_P2SB_IBDF_DEV 0x00F8
+#define B_PCH_P2SB_IBDF_FUNC 0x0007
+#define R_PCH_P2SB_HBDF 0x70
+#define B_PCH_P2SB_HBDF_BUF 0xFF00
+#define B_PCH_P2SB_HBDF_DEV 0x00F8
+#define B_PCH_P2SB_HBDF_FUNC 0x0007
+#define R_PCH_P2SB_80 0x80
+#define R_PCH_P2SB_84 0x84
+#define R_PCH_P2SB_88 0x88
+#define R_PCH_P2SB_8C 0x8C
+#define R_PCH_P2SB_90 0x90
+#define R_PCH_P2SB_94 0x94
+#define R_PCH_P2SB_98 0x98
+#define R_PCH_P2SB_9C 0x9C
+
+#define R_PCH_P2SB_DISPBDF 0xA0
+#define B_PCH_P2SB_DISPBDF_DTBLK 0x00070000
+#define B_PCH_P2SB_DISPBDF_BUF 0x0000FF00
+#define B_PCH_P2SB_DISPBDF_DEV 0x000000F8
+#define B_PCH_P2SB_DISPBDF_FUNC 0x00000007
+#define R_PCH_P2SB_ICCOS 0xA4
+#define B_PCH_P2SB_ICCOS_MODBASE 0xFF00
+#define B_PCH_P2SB_ICCOS_BUFBASE 0x00FF
+#define R_PCH_P2SB_EPMASK0 0xB0
+#define R_PCH_P2SB_EPMASK1 0xB4
+#define R_PCH_P2SB_EPMASK2 0xB8
+#define R_PCH_P2SB_EPMASK3 0xBC
+#define R_PCH_P2SB_EPMASK4 0xC0
+#define R_PCH_P2SB_EPMASK5 0xC4
+#define R_PCH_P2SB_EPMASK6 0xC8
+#define R_PCH_P2SB_EPMASK7 0xCC
+
+//
+// Definition for SBI
+//
+#define R_PCH_P2SB_SBIADDR 0xD0
+#define B_PCH_P2SB_SBIADDR_DESTID 0xFF000000
+#define B_PCH_P2SB_SBIADDR_RS 0x000F0000
+#define B_PCH_P2SB_SBIADDR_OFFSET 0x0000FFFF
+#define R_PCH_P2SB_SBIDATA 0xD4
+#define B_PCH_P2SB_SBIDATA_DATA 0xFFFFFFFF
+#define R_PCH_P2SB_SBISTAT 0xD8
+#define B_PCH_P2SB_SBISTAT_OPCODE 0xFF00
+#define B_PCH_P2SB_SBISTAT_POSTED BIT7
+#define B_PCH_P2SB_SBISTAT_RESPONSE 0x0006
+#define N_PCH_P2SB_SBISTAT_RESPONSE 1
+#define B_PCH_P2SB_SBISTAT_INITRDY BIT0
+#define R_PCH_P2SB_SBIRID 0xDA
+#define B_PCH_P2SB_SBIRID_FBE 0xF000
+#define B_PCH_P2SB_SBIRID_BAR 0x0700
+#define B_PCH_P2SB_SBIRID_FID 0x00FF
+#define R_PCH_P2SB_SBIEXTADDR 0xDC
+#define B_PCH_P2SB_SBIEXTADDR_ADDR 0xFFFFFFFF
+
+//
+// Others
+//
+#define R_PCH_P2SB_E0 0xE0
+#define R_PCH_P2SB_E4 0xE4
+#define R_PCH_P2SB_E8 0xE8
+#define R_PCH_P2SB_EA 0xEA
+#define R_PCH_P2SB_F4 0xF4
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h
new file mode 100644
index 0000000000..704f77c52f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h
@@ -0,0 +1,524 @@
+/** @file
+ Register names for PCH PCI-E root port devices
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_PCIE_H_
+#define _PCH_REGS_PCIE_H_
+
+//
+// PCH PCI Express Root Ports (D28:F0..7, D29:F0..7, D27:F0..7)
+//
+#define PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS 28
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 0
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 1
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 2
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 3
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5 4
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6 5
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7 6
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8 7
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_9 0
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_10 1
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_11 2
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_12 3
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_13 4
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_14 5
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_15 6
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_16 7
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_17 0
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_18 1
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_19 2
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_20 3
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_21 4
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_22 5
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_23 6
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_24 7
+
+#define V_PCH_PCIE_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT1 0xA110 ///< PCI Express Root Port #1, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT2 0xA111 ///< PCI Express Root Port #2, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT3 0xA112 ///< PCI Express Root Port #3, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT4 0xA113 ///< PCI Express Root Port #4, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT5 0xA114 ///< PCI Express Root Port #5, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT6 0xA115 ///< PCI Express Root Port #6, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT7 0xA116 ///< PCI Express Root Port #7, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT8 0xA117 ///< PCI Express Root Port #8, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT9 0xA118 ///< PCI Express Root Port #9, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT10 0xA119 ///< PCI Express Root Port #10, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT11 0xA11A ///< PCI Express Root Port #11, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT12 0xA11B ///< PCI Express Root Port #12, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT13 0xA11C ///< PCI Express Root Port #13, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT14 0xA11D ///< PCI Express Root Port #14, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT15 0xA11E ///< PCI Express Root Port #15, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT16 0xA11F ///< PCI Express Root Port #16, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT17 0xA167 ///< PCI Express Root Port #17, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT18 0xA168 ///< PCI Express Root Port #18, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT19 0xA169 ///< PCI Express Root Port #19, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT20 0xA16A ///< PCI Express Root Port #20, SKL PCH H
+
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT1 0xA290 ///< PCI Express Root Port #1, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT2 0xA291 ///< PCI Express Root Port #2, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT3 0xA292 ///< PCI Express Root Port #3, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT4 0xA293 ///< PCI Express Root Port #4, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT5 0xA294 ///< PCI Express Root Port #5, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT6 0xA295 ///< PCI Express Root Port #6, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT7 0xA296 ///< PCI Express Root Port #7, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT8 0xA297 ///< PCI Express Root Port #8, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT9 0xA298 ///< PCI Express Root Port #9, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT10 0xA299 ///< PCI Express Root Port #10, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT11 0xA29A ///< PCI Express Root Port #11, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT12 0xA29B ///< PCI Express Root Port #12, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT13 0xA29C ///< PCI Express Root Port #13, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT14 0xA29D ///< PCI Express Root Port #14, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT15 0xA29E ///< PCI Express Root Port #15, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT16 0xA29F ///< PCI Express Root Port #16, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT17 0xA2E7 ///< PCI Express Root Port #17, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT18 0xA2E8 ///< PCI Express Root Port #18, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT19 0xA2E9 ///< PCI Express Root Port #19, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT20 0xA2EA ///< PCI Express Root Port #20, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT21 0xA2EB ///< PCI Express Root Port #21, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT22 0xA2EC ///< PCI Express Root Port #22, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT23 0xA2ED ///< PCI Express Root Port #23, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT24 0xA2EE ///< PCI Express Root Port #24, KBL PCH H
+
+
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT1 0x9D10 ///< PCI Express Root Port #1, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT2 0x9D11 ///< PCI Express Root Port #2, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT3 0x9D12 ///< PCI Express Root Port #3, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT4 0x9D13 ///< PCI Express Root Port #4, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT5 0x9D14 ///< PCI Express Root Port #5, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT6 0x9D15 ///< PCI Express Root Port #6, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT7 0x9D16 ///< PCI Express Root Port #7, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT8 0x9D17 ///< PCI Express Root Port #8, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT9 0x9D18 ///< PCI Express Root Port #9, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT10 0x9D19 ///< PCI Express Root Port #10, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT11 0x9D1A ///< PCI Express Root Port #11, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT12 0x9D1B ///< PCI Express Root Port #12, SKL PCH LP PCIe Device ID
+
+#define R_PCH_PCIE_CLIST 0x40
+#define R_PCH_PCIE_XCAP (R_PCH_PCIE_CLIST + R_PCIE_XCAP_OFFSET)
+#define R_PCH_PCIE_DCAP (R_PCH_PCIE_CLIST + R_PCIE_DCAP_OFFSET)
+#define R_PCH_PCIE_DCTL (R_PCH_PCIE_CLIST + R_PCIE_DCTL_OFFSET)
+#define R_PCH_PCIE_DSTS (R_PCH_PCIE_CLIST + R_PCIE_DSTS_OFFSET)
+#define R_PCH_PCIE_LCAP (R_PCH_PCIE_CLIST + R_PCIE_LCAP_OFFSET)
+#define B_PCH_PCIE_LCAP_PN 0xFF000000
+#define N_PCH_PCIE_LCAP_PN 24
+#define R_PCH_PCIE_LCTL (R_PCH_PCIE_CLIST + R_PCIE_LCTL_OFFSET)
+#define R_PCH_PCIE_LSTS (R_PCH_PCIE_CLIST + R_PCIE_LSTS_OFFSET)
+#define R_PCH_PCIE_SLCAP (R_PCH_PCIE_CLIST + R_PCIE_SLCAP_OFFSET)
+#define R_PCH_PCIE_SLCTL (R_PCH_PCIE_CLIST + R_PCIE_SLCTL_OFFSET)
+#define R_PCH_PCIE_SLSTS (R_PCH_PCIE_CLIST + R_PCIE_SLSTS_OFFSET)
+#define R_PCH_PCIE_RCTL (R_PCH_PCIE_CLIST + R_PCIE_RCTL_OFFSET)
+#define R_PCH_PCIE_RSTS (R_PCH_PCIE_CLIST + R_PCIE_RSTS_OFFSET)
+#define R_PCH_PCIE_DCAP2 (R_PCH_PCIE_CLIST + R_PCIE_DCAP2_OFFSET)
+#define R_PCH_PCIE_DCTL2 (R_PCH_PCIE_CLIST + R_PCIE_DCTL2_OFFSET)
+#define R_PCH_PCIE_LCTL2 (R_PCH_PCIE_CLIST + R_PCIE_LCTL2_OFFSET)
+#define R_PCH_PCIE_LSTS2 (R_PCH_PCIE_CLIST + R_PCIE_LSTS2_OFFSET)
+
+
+#define R_PCH_PCIE_MID 0x80
+#define S_PCH_PCIE_MID 2
+#define R_PCH_PCIE_MC 0x82
+#define S_PCH_PCIE_MC 2
+#define R_PCH_PCIE_MA 0x84
+#define S_PCH_PCIE_MA 4
+#define R_PCH_PCIE_MD 0x88
+#define S_PCH_PCIE_MD 2
+
+#define R_PCH_PCIE_SVCAP 0x90
+#define S_PCH_PCIE_SVCAP 2
+#define R_PCH_PCIE_SVID 0x94
+#define S_PCH_PCIE_SVID 4
+
+#define R_PCH_PCIE_PMCAP 0xA0
+#define R_PCH_PCIE_PMCS (R_PCH_PCIE_PMCAP + R_PCIE_PMCS_OFFST)
+#define R_PCH_PCIE_MPC2 0xD4
+#define S_PCH_PCIE_MPC2 4
+#define B_PCH_PCIE_MPC2_PTNFAE BIT12
+#define B_PCH_PCIE_MPC2_LSTP BIT6
+#define B_PCH_PCIE_MPC2_IEIME BIT5
+#define B_PCH_PCIE_MPC2_ASPMCOEN BIT4
+#define B_PCH_PCIE_MPC2_ASPMCO (BIT3 | BIT2)
+#define V_PCH_PCIE_MPC2_ASPMCO_DISABLED 0
+#define V_PCH_PCIE_MPC2_ASPMCO_L0S (1 << 2)
+#define V_PCH_PCIE_MPC2_ASPMCO_L1 (2 << 2)
+#define V_PCH_PCIE_MPC2_ASPMCO_L0S_L1 (3 << 2)
+#define B_PCH_PCIE_MPC2_EOIFD BIT1
+
+#define R_PCH_PCIE_MPC 0xD8
+#define S_PCH_PCIE_MPC 4
+#define B_PCH_PCIE_MPC_PMCE BIT31
+#define B_PCH_PCIE_MPC_HPCE BIT30
+#define B_PCH_PCIE_MPC_MMBNCE BIT27
+#define B_PCH_PCIE_MPC_P8XDE BIT26
+#define B_PCH_PCIE_MPC_IRRCE BIT25
+#define B_PCH_PCIE_MPC_SRL BIT23
+#define B_PCH_PCIE_MPC_UCEL (BIT20 | BIT19 | BIT18)
+#define N_PCH_PCIE_MPC_UCEL 18
+#define B_PCH_PCIE_MPC_CCEL (BIT17 | BIT16 | BIT15)
+#define N_PCH_PCIE_MPC_CCEL 15
+#define B_PCH_PCIE_MPC_PCIESD (BIT14 | BIT13)
+#define N_PCH_PCIE_MPC_PCIESD 13
+#define V_PCH_PCIE_MPC_PCIESD_GEN1 1
+#define V_PCH_PCIE_MPC_PCIESD_GEN2 2
+#define B_PCH_PCIE_MPC_MCTPSE BIT3
+#define B_PCH_PCIE_MPC_HPME BIT1
+#define N_PCH_PCIE_MPC_HPME 1
+#define B_PCH_PCIE_MPC_PMME BIT0
+
+#define R_PCH_PCIE_SMSCS 0xDC
+#define S_PCH_PCIE_SMSCS 4
+#define B_PCH_PCIE_SMSCS_PMCS BIT31
+#define N_PCH_PCIE_SMSCS_LERSMIS 5
+#define N_PCH_PCIE_SMSCS_HPLAS 4
+#define N_PCH_PCIE_SMSCS_HPPDM 1
+
+#define R_PCH_PCIE_RPDCGEN 0xE1
+#define S_PCH_PCIE_RPDCGEN 1
+#define B_PCH_PCIE_RPDCGEN_RPSCGEN BIT7
+#define B_PCH_PCIE_RPDCGEN_PTOCGE BIT6
+#define B_PCH_PCIE_RPDCGEN_LCLKREQEN BIT5
+#define B_PCH_PCIE_RPDCGEN_BBCLKREQEN BIT4
+#define B_PCH_PCIE_RPDCGEN_SRDBCGEN BIT2
+#define B_PCH_PCIE_RPDCGEN_RPDLCGEN BIT1
+#define B_PCH_PCIE_RPDCGEN_RPDBCGEN BIT0
+
+
+#define R_PCH_PCIE_PWRCTL 0xE8
+#define B_PCH_PCIE_PWRCTL_LTSSMRTC BIT20
+#define B_PCH_PCIE_PWRCTL_WPDMPGEP BIT17
+#define B_PCH_PCIE_PWRCTL_DBUPI BIT15
+#define B_PCH_PCIE_PWRCTL_TXSWING BIT13
+#define B_PCH_PCIE_PWRCTL_RPL1SQPOL BIT1
+#define B_PCH_PCIE_PWRCTL_RPDTSQPOL BIT0
+
+#define R_PCH_PCIE_DC 0xEC
+#define B_PCH_PCIE_DC_PCIBEM BIT2
+
+#define R_PCH_PCIE_PHYCTL2 0xF5
+#define B_PCH_PCIE_PHYCTL2_TDFT (BIT7 | BIT6)
+#define B_PCH_PCIE_PHYCTL2_TXCFGCHGWAIT (BIT5 | BIT4)
+#define N_PCH_PCIE_PHYCTL2_TXCFGCHGWAIT 4
+#define B_PCH_PCIE_PHYCTL2_PXPG3PLLOFFEN BIT1
+#define B_PCH_PCIE_PHYCTL2_PXPG2PLLOFFEN BIT0
+
+#define R_PCH_PCIE_IOSFSBCS 0xF7
+#define B_PCH_PCIE_IOSFSBCS_SCPTCGE BIT6
+#define B_PCH_PCIE_IOSFSBCS_SIID (BIT3 | BIT2)
+
+#define R_PCH_PCIE_STRPFUSECFG 0xFC
+#define B_PCH_PCIE_STRPFUSECFG_PXIP (BIT27 | BIT26 | BIT25 | BIT24)
+#define N_PCH_PCIE_STRPFUSECFG_PXIP 24
+#define B_PCH_PCIE_STRPFUSECFG_RPC (BIT15 | BIT14)
+#define V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1 0
+#define V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1 1
+#define V_PCH_PCIE_STRPFUSECFG_RPC_2_2 2
+#define V_PCH_PCIE_STRPFUSECFG_RPC_4 3
+#define N_PCH_PCIE_STRPFUSECFG_RPC 14
+#define B_PCH_PCIE_STRPFUSECFG_MODPHYIOPMDIS BIT9
+#define B_PCH_PCIE_STRPFUSECFG_PLLSHTDWNDIS BIT8
+#define B_PCH_PCIE_STRPFUSECFG_STPGATEDIS BIT7
+#define B_PCH_PCIE_STRPFUSECFG_ASPMDIS BIT6
+#define B_PCH_PCIE_STRPFUSECFG_LDCGDIS BIT5
+#define B_PCH_PCIE_STRPFUSECFG_LTCGDIS BIT4
+#define B_PCH_PCIE_STRPFUSECFG_CDCGDIS BIT3
+#define B_PCH_PCIE_STRPFUSECFG_DESKTOPMOB BIT2
+
+//
+//PCI Express Extended Capability Registers
+//
+
+#define R_PCH_PCIE_EXCAP_OFFSET 0x100
+
+#define R_PCH_PCIE_EX_AECH 0x100 ///< Advanced Error Reporting Capability Header
+#define V_PCH_PCIE_EX_AEC_CV 0x1
+#define R_PCH_PCIE_EX_UEM (R_PCH_PCIE_EX_AECH + R_PCIE_EX_UEM_OFFSET) // Uncorrectable Error Mask
+
+#define R_PCH_PCIE_EX_CES 0x110 ///< Correctable Error Status
+#define B_PCH_PCIE_EX_CES_BD BIT7 ///< Bad DLLP Status
+#define B_PCH_PCIE_EX_CES_BT BIT6 ///< Bad TLP Status
+#define B_PCH_PCIE_EX_CES_RE BIT0 ///< Receiver Error Status
+
+
+//CES.RE, CES.BT, CES.BD
+
+#define R_PCH_PCIE_EX_ACSECH 0x140 ///< ACS Extended Capability Header
+#define V_PCH_PCIE_EX_ACS_CV 0x1
+#define R_PCH_PCIE_EX_ACSCAPR (R_PCH_PCIE_EX_ACSECH + R_PCIE_EX_ACSCAPR_OFFSET)
+
+#define R_PCH_PCIE_EX_L1SECH 0x200 ///< L1 Sub-States Extended Capability Header
+#define V_PCH_PCIE_EX_L1S_CV 0x1
+#define R_PCH_PCIE_EX_L1SCAP (R_PCH_PCIE_EX_L1SECH + R_PCIE_EX_L1SCAP_OFFSET)
+#define R_PCH_PCIE_EX_L1SCTL1 (R_PCH_PCIE_EX_L1SECH + R_PCIE_EX_L1SCTL1_OFFSET)
+#define R_PCH_PCIE_EX_L1SCTL2 (R_PCH_PCIE_EX_L1SECH + R_PCIE_EX_L1SCTL2_OFFSET)
+
+#define R_PCH_PCIE_EX_SPEECH 0x220 ///< Secondary PCI Express Extended Capability Header
+#define V_PCH_PCIE_EX_SPEECH_CV 0x1
+
+#define R_PCH_PCIE_EX_LCTL3 (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_LCTL3_OFFSET)
+#define R_PCH_PCIE_EX_LES (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_LES_OFFSET)
+#define R_PCH_PCIE_EX_LECTL (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_L01EC_OFFSET)
+#define B_PCH_PCIE_EX_LECTL_UPTPH (BIT14 | BIT13 | BIT12)
+#define N_PCH_PCIE_EX_LECTL_UPTPH 12
+#define B_PCH_PCIE_EX_LECTL_UPTP 0x0F00
+#define N_PCH_PCIE_EX_LECTL_UPTP 8
+#define B_PCH_PCIE_EX_LECTL_DPTPH (BIT6 | BIT5 | BIT4)
+#define N_PCH_PCIE_EX_LECTL_DPTPH 4
+#define B_PCH_PCIE_EX_LECTL_DPTP 0x000F
+#define N_PCH_PCIE_EX_LECTL_DPTP 0
+
+#define R_PCH_PCIE_EX_L01EC (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_L01EC_OFFSET)
+#define R_PCH_PCIE_EX_L23EC (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_L23EC_OFFSET)
+
+#define R_PCH_PCIE_PCIERTP1 0x300
+#define R_PCH_PCIE_PCIERTP2 0x304
+#define R_PCH_PCIE_PCIENFTS 0x314
+#define R_PCH_PCIE_PCIEL0SC 0x318
+
+#define R_PCH_PCIE_PCIECFG2 0x320
+#define B_PCH_PCIE_PCIECFG2_LBWSSTE BIT30
+#define B_PCH_PCIE_PCIECFG2_RLLG3R BIT27
+#define B_PCH_PCIE_PCIECFG2_CROAOV BIT24
+#define B_PCH_PCIE_PCIECFG2_CROAOE BIT23
+#define B_PCH_PCIE_PCIECFG2_CRSREN BIT22
+#define B_PCH_PCIE_PCIECFG2_PMET (BIT21 | BIT20)
+#define V_PCH_PCIE_PCIECFG2_PMET 1
+#define N_PCH_PCIE_PCIECFG2_PMET 20
+
+#define R_PCH_PCIE_PCIEDBG 0x324
+#define B_PCH_PCIE_PCIEDBG_USSP (BIT27 | BIT26)
+#define B_PCH_PCIE_PCIEDBG_LGCLKSQEXITDBTIMERS (BIT25 | BIT24)
+#define B_PCH_PCIE_PCIEDBG_CTONFAE BIT14
+#define B_PCH_PCIE_PCIEDBG_SQOL0 BIT7
+#define B_PCH_PCIE_PCIEDBG_SPCE BIT5
+#define B_PCH_PCIE_PCIEDBG_LR BIT4
+
+#define R_PCH_PCIE_PCIESTS1 0x328
+#define B_PCH_PCIE_PCIESTS1_LTSMSTATE 0xFF000000
+#define N_PCH_PCIE_PCIESTS1_LTSMSTATE 24
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DETRDY 0x01
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DETRDYECINP1CG 0x0E
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_L0 0x33
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DISWAIT 0x5E
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DISWAITPG 0x60
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_RECOVERYSPEEDREADY 0x6C
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_RECOVERYLNK2DETECT 0x6F
+
+
+#define B_PCH_PCIE_PCIESTS1_LNKSTAT (BIT22 | BIT21 | BIT20 | BIT19)
+#define N_PCH_PCIE_PCIESTS1_LNKSTAT 19
+#define V_PCH_PCIE_PCIESTS1_LNKSTAT_L0 0x7
+
+#define R_PCH_PCIE_PCIESTS2 0x32C
+#define B_PCH_PCIE_PCIESTS2_P4PNCCWSSCMES BIT31
+#define B_PCH_PCIE_PCIESTS2_P3PNCCWSSCMES BIT30
+#define B_PCH_PCIE_PCIESTS2_P2PNCCWSSCMES BIT29
+#define B_PCH_PCIE_PCIESTS2_P1PNCCWSSCMES BIT28
+#define B_PCH_PCIE_PCIESTS2_CLRE 0x0000F000
+#define N_PCH_PCIE_PCIESTS2_CLRE 12
+
+#define R_PCH_PCIE_PCIEALC 0x338
+#define B_PCH_PCIE_PCIEALC_ITLRCLD BIT29
+#define B_PCH_PCIE_PCIEALC_ILLRCLD BIT28
+#define B_PCH_PCIE_PCIEALC_BLKDQDA BIT26
+#define R_PCH_PCIE_PHYCTL4 0x408
+#define B_PCH_PCIE_PHYCTL4_SQDIS BIT27
+
+#define R_PCH_PCIE_PCIEPMECTL2 0x424
+#define B_PCH_PCIE_PCIEPMECTL2_PHYCLPGE BIT11
+#define B_PCH_PCIE_PCIEPMECTL2_FDCPGE BIT8
+#define B_PCH_PCIE_PCIEPMECTL2_DETSCPGE BIT7
+#define B_PCH_PCIE_PCIEPMECTL2_L23RDYSCPGE BIT6
+#define B_PCH_PCIE_PCIEPMECTL2_DISSCPGE BIT5
+#define B_PCH_PCIE_PCIEPMECTL2_L1SCPGE BIT4
+
+#define R_PCH_PCIE_PCE 0x428
+#define B_PCH_PCIE_PCE_HAE BIT5
+#define B_PCH_PCIE_PCE_PMCRE BIT0
+
+#define R_PCH_PCIE_EQCFG1 0x450
+#define S_PCH_PCIE_EQCFG1 4
+#define B_PCH_PCIE_EQCFG1_REC 0xFF000000
+#define N_PCH_PCIE_EQCFG1_REC 24
+#define B_PCH_PCIE_EQCFG1_REIFECE BIT23
+#define N_PCH_PCIE_EQCFG1_LERSMIE 21
+#define B_PCH_PCIE_EQCFG1_LEP23B BIT18
+#define B_PCH_PCIE_EQCFG1_LEP3B BIT17
+#define B_PCH_PCIE_EQCFG1_RTLEPCEB BIT16
+#define B_PCH_PCIE_EQCFG1_RTPCOE BIT15
+#define B_PCH_PCIE_EQCFG1_HPCMQE BIT13
+#define B_PCH_PCIE_EQCFG1_HAED BIT12
+#define B_PCH_PCIE_EQCFG1_EQTS2IRRC BIT7
+#define B_PCH_PCIE_EQCFG1_TUPP BIT1
+
+#define R_PCH_PCIE_RTPCL1 0x454
+#define B_PCH_PCIE_RTPCL1_PCM BIT31
+#define B_PCH_PCIE_RTPCL1_RTPRECL2PL4 0x3F000000
+#define B_PCH_PCIE_RTPCL1_RTPOSTCL1PL3 0xFC0000
+#define B_PCH_PCIE_RTPCL1_RTPRECL1PL2 0x3F000
+#define B_PCH_PCIE_RTPCL1_RTPOSTCL0PL1 0xFC0
+#define B_PCH_PCIE_RTPCL1_RTPRECL0PL0 0x3F
+
+#define R_PCH_PCIE_RTPCL2 0x458
+#define B_PCH_PCIE_RTPCL2_RTPOSTCL3PL 0x3F000
+#define B_PCH_PCIE_RTPCL2_RTPRECL3PL6 0xFC0
+#define B_PCH_PCIE_RTPCL2_RTPOSTCL2PL5 0x3F
+
+#define R_PCH_PCIE_RTPCL3 0x45C
+#define B_PCH_PCIE_RTPCL3_RTPRECL7 0x3F000000
+#define B_PCH_PCIE_RTPCL3_RTPOSTCL6 0xFC0000
+#define B_PCH_PCIE_RTPCL3_RTPRECL6 0x3F000
+#define B_PCH_PCIE_RTPCL3_RTPOSTCL5 0xFC0
+#define B_PCH_PCIE_RTPCL3_RTPRECL5PL10 0x3F
+
+#define R_PCH_PCIE_RTPCL4 0x460
+#define B_PCH_PCIE_RTPCL4_RTPOSTCL9 0x3F000000
+#define B_PCH_PCIE_RTPCL4_RTPRECL9 0xFC0000
+#define B_PCH_PCIE_RTPCL4_RTPOSTCL8 0x3F000
+#define B_PCH_PCIE_RTPCL4_RTPRECL8 0xFC0
+#define B_PCH_PCIE_RTPCL4_RTPOSTCL7 0x3F
+
+#define R_PCH_PCIE_FOMS 0x464
+#define B_PCH_PCIE_FOMS_I (BIT30 | BIT29)
+#define N_PCH_PCIE_FOMS_I 29
+#define B_PCH_PCIE_FOMS_LN 0x1F000000
+#define N_PCH_PCIE_FOMS_LN 24
+#define B_PCH_PCIE_FOMS_FOMSV 0x00FFFFFF
+#define B_PCH_PCIE_FOMS_FOMSV0 0x000000FF
+#define N_PCH_PCIE_FOMS_FOMSV0 0
+#define B_PCH_PCIE_FOMS_FOMSV1 0x0000FF00
+#define N_PCH_PCIE_FOMS_FOMSV1 8
+#define B_PCH_PCIE_FOMS_FOMSV2 0x00FF0000
+#define N_PCH_PCIE_FOMS_FOMSV2 16
+
+#define R_PCH_PCIE_HAEQ 0x468
+#define B_PCH_PCIE_HAEQ_HAPCCPI (BIT31 | BIT30 | BIT29 | BIT28)
+#define N_PCH_PCIE_HAEQ_HAPCCPI 28
+#define B_PCH_PCIE_HAEQ_MACFOMC BIT19
+
+#define R_PCH_PCIE_LTCO1 0x470
+#define B_PCH_PCIE_LTCO1_L1TCOE BIT25
+#define B_PCH_PCIE_LTCO1_L0TCOE BIT24
+#define B_PCH_PCIE_LTCO1_L1TPOSTCO 0xFC0000
+#define N_PCH_PCIE_LTCO1_L1TPOSTCO 18
+#define B_PCH_PCIE_LTCO1_L1TPRECO 0x3F000
+#define N_PCH_PCIE_LTCO1_L1TPRECO 12
+#define B_PCH_PCIE_LTCO1_L0TPOSTCO 0xFC0
+#define N_PCH_PCIE_LTCO1_L0TPOSTCO 6
+#define B_PCH_PCIE_LTCO1_L0TPRECO 0x3F
+#define N_PCH_PCIE_LTCO1_L0TPRECO 0
+
+#define R_PCH_PCIE_LTCO2 0x474
+#define B_PCH_PCIE_LTCO2_L3TCOE BIT25
+#define B_PCH_PCIE_LTCO2_L2TCOE BIT24
+#define B_PCH_PCIE_LTCO2_L3TPOSTCO 0xFC0000
+#define B_PCH_PCIE_LTCO2_L3TPRECO 0x3F000
+#define B_PCH_PCIE_LTCO2_L2TPOSTCO 0xFC0
+#define B_PCH_PCIE_LTCO2_L2TPRECO 0x3F
+
+#define R_PCH_PCIE_G3L0SCTL 0x478
+#define B_PCH_PCIE_G3L0SCTL_G3UCNFTS 0x0000FF00
+#define B_PCH_PCIE_G3L0SCTL_G3CCNFTS 0x000000FF
+
+#define R_PCH_PCIE_EQCFG2 0x47C
+#define B_PCH_PCIE_EQCFG2_NTIC 0xFF000000
+#define B_PCH_PCIE_EQCFG2_EMD BIT23
+#define B_PCH_PCIE_EQCFG2_NTSS (BIT22 | BIT21 | BIT20)
+#define B_PCH_PCIE_EQCFG2_PCET (BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_PCIE_EQCFG2_PCET 16
+#define B_PCH_PCIE_EQCFG2_HAPCSB (BIT15 | BIT14 | BIT13 | BIT12)
+#define N_PCH_PCIE_EQCFG2_HAPCSB 12
+#define B_PCH_PCIE_EQCFG2_NTEME BIT11
+#define B_PCH_PCIE_EQCFG2_MPEME BIT10
+#define B_PCH_PCIE_EQCFG2_REWMETM (BIT9 | BIT8)
+#define B_PCH_PCIE_EQCFG2_REWMET 0xFF
+
+#define R_PCH_PCIE_MM 0x480
+#define B_PCH_PCIE_MM_MSST 0xFFFFFF00
+#define N_PCH_PCIE_MM_MSST 8
+#define B_PCH_PCIE_MM_MSS 0xFF
+
+//
+//PCI Express Extended End Point Capability Registers
+//
+
+#define R_PCH_PCIE_LTRECH_OFFSET 0
+#define R_PCH_PCIE_LTRECH_CID 0x0018
+#define R_PCH_PCIE_LTRECH_MSLR_OFFSET 0x04
+#define R_PCH_PCIE_LTRECH_MNSLR_OFFSET 0x06
+
+
+//
+// PCIE PCRs (PID:SPA SPB SPC SPD SPE SPF)
+//
+#define R_PCH_PCR_SPX_PCD 0 ///< Port configuration and disable
+#define B_PCH_PCR_SPX_PCD_RP1FN (BIT2 | BIT1 | BIT0) ///< Port 1 Function Number
+#define B_PCH_PCR_SPX_PCD_RP1CH BIT3 ///< Port 1 config hide
+#define B_PCH_PCR_SPX_PCD_RP2FN (BIT6 | BIT5 | BIT4) ///< Port 2 Function Number
+#define B_PCH_PCR_SPX_PCD_RP2CH BIT7 ///< Port 2 config hide
+#define B_PCH_PCR_SPX_PCD_RP3FN (BIT10 | BIT9 | BIT8) ///< Port 3 Function Number
+#define B_PCH_PCR_SPX_PCD_RP3CH BIT11 ///< Port 3 config hide
+#define B_PCH_PCR_SPX_PCD_RP4FN (BIT14 | BIT13 | BIT12) ///< Port 4 Function Number
+#define B_PCH_PCR_SPX_PCD_RP4CH BIT15 ///< Port 4 config hide
+#define S_PCH_PCR_SPX_PCD_RP_FIELD 4 ///< 4 bits for each RP FN
+#define B_PCH_PCR_SPX_PCD_P1D BIT16 ///< Port 1 disable
+#define B_PCH_PCR_SPX_PCD_P2D BIT17 ///< Port 2 disable
+#define B_PCH_PCR_SPX_PCD_P3D BIT18 ///< Port 3 disable
+#define B_PCH_PCR_SPX_PCD_P4D BIT19 ///< Port 4 disable
+#define B_PCH_PCR_SPX_PCD_SRL BIT31 ///< Secured Register Lock
+
+#define R_PCH_PCR_SPX_PCIEHBP 0x0004 ///< PCI Express high-speed bypass
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEHBPME BIT0 ///< PCIe HBP mode enable
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEGMO (BIT2 | BIT1) ///< PCIe gen mode override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIETIL0O BIT3 ///< PCIe transmitter-in-L0 override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIERIL0O BIT4 ///< PCIe receiver-in-L0 override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIELRO BIT5 ///< PCIe link recovery override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIELDO BIT6 ///< PCIe link down override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIESSM BIT7 ///< PCIe SKP suppression mode
+#define B_PCH_PCR_SPX_PCIEHBP_PCIESST BIT8 ///< PCIe suppress SKP transmission
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEHBPPS (BIT13 | BIT12) ///< PCIe HBP port select
+#define B_PCH_PCR_SPX_PCIEHBP_CRCSEL (BIT15 | BIT14) ///< CRC select
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEHBPCRC 0xFFFF0000 ///< PCIe HBP CRC
+
+
+//
+// ICC PCR (PID: ICC)
+//
+#define R_PCH_PCR_ICC_TMCSRCCLK 0x1000 ///< Timing Control SRC Clock Register
+#define R_PCH_PCR_ICC_TMCSRCCLK2 0x1004 ///< Timing Control SRC Clock Register 2
+#define R_PCH_PCR_ICC_MSKCKRQ 0x100C ///< Mask Control CLKREQ
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h
new file mode 100644
index 0000000000..eac209a149
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h
@@ -0,0 +1,111 @@
+/** @file
+ Register names for PCH private chipset register
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_PCR_H_
+#define _PCH_REGS_PCR_H_
+
+///
+/// Definition for PCR base address (defined in PchReservedResources.h)
+///
+//#define PCH_PCR_BASE_ADDRESS 0xFD000000
+//#define PCH_PCR_MMIO_SIZE 0x01000000
+/**
+ Definition for PCR address
+ The PCR address is used to the PCR MMIO programming
+**/
+#define PCH_PCR_ADDRESS(Pid, Offset) (PCH_PCR_BASE_ADDRESS | ((UINT8)(Pid) << 16) | (UINT16)(Offset))
+
+/**
+ PCH PCR boot script accessing macro
+ Those macros are only available for DXE phase.
+**/
+#define PCH_PCR_BOOT_SCRIPT_WRITE(Width, Pid, Offset, Count, Buffer) \
+ S3BootScriptSaveMemWrite (Width, PCH_PCR_ADDRESS (Pid, Offset), Count, Buffer); \
+ S3BootScriptSaveMemPoll (Width, PCH_PCR_ADDRESS (Pid, Offset), Buffer, Buffer, 1, 1);
+
+#define PCH_PCR_BOOT_SCRIPT_READ_WRITE(Width, Pid, Offset, DataOr, DataAnd) \
+ S3BootScriptSaveMemReadWrite (Width, PCH_PCR_ADDRESS (Pid, Offset), DataOr, DataAnd); \
+ S3BootScriptSaveMemPoll (Width, PCH_PCR_ADDRESS (Pid, Offset), DataOr, DataOr, 1, 1);
+
+
+/**
+ Definition for SBI PID
+ The PCH_SBI_PID defines the PID for PCR MMIO programming and PCH SBI programming as well.
+**/
+#define PID_DMI 0xEF
+#define PID_ESPISPI 0xEE
+#define PID_OPIPHY 0xEC
+#define PID_MODPHY0 0xEA
+#define PID_MODPHY1 0xE9
+#define PID_OTG 0xE5
+#define PID_SPF 0xC9 // Available only in KBL PCH H
+#define PID_SPE 0xE4 // Reserved in SKL PCH LP
+#define PID_SPD 0xE3 // Reserved in SKL PCH LP
+#define PID_SPC 0xE2
+#define PID_SPB 0xE1
+#define PID_SPA 0xE0
+#define PID_ICC 0xDC
+#define PID_DSP 0xD7
+#define PID_FIA 0xCF
+#define PID_SERIALIO 0xCB
+#define PID_USB2 0xCA
+#define PID_LPC 0xC7
+#define PID_SMB 0xC6
+#define PID_ITSS 0xC4
+#define PID_RTC 0xC3
+#define PID_SCS 0xC0 // Reserved in SKL PCH H
+#define PID_ISHBR 0xBF
+#define PID_ISH 0xBE
+#define PID_PSF4 0xBD
+#define PID_PSF3 0xBC
+#define PID_PSF2 0xBB
+#define PID_PSF1 0xBA
+#define PID_DCI 0xB8
+#define PID_MMP0 0xB0 // for SKL-LP only
+#define PID_MODPHY4 0xB0 // for KBL-H only
+#define PID_GPIOCOM0 0xAF
+#define PID_GPIOCOM1 0xAE
+#define PID_GPIOCOM2 0xAD
+#define PID_GPIOCOM3 0xAC
+#define PID_CAM_FLS 0xAA
+#define PID_MODPHY2 0xA9
+#define PID_MODPHY3 0xA8
+#define PID_CAM_CHC 0xA1
+#define PID_CSME12 0x9C
+#define PID_CSME0 0x90
+#define PID_CSME_PSF 0x8F
+#define PID_PSTH 0x89
+
+typedef UINT8 PCH_SBI_PID;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h
new file mode 100644
index 0000000000..d4c048ffe3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h
@@ -0,0 +1,652 @@
+/** @file
+ Register names for PCH PMC device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_PMC_H_
+#define _PCH_REGS_PMC_H_
+
+//
+// PMC Registers (D31:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_PMC 31
+#define PCI_FUNCTION_NUMBER_PCH_PMC 2
+
+#define R_PCH_PMC_PM_DATA_BAR 0x10
+#define B_PCH_PMC_PM_DATA_BAR 0xFFFFC000
+#define R_PCH_PMC_ACPI_BASE 0x40
+#define B_PCH_PMC_ACPI_BASE_BAR 0xFFFC
+#define R_PCH_PMC_ACPI_CNT 0x44
+#define B_PCH_PMC_ACPI_CNT_PWRM_EN BIT8 ///< PWRM enable
+#define B_PCH_PMC_ACPI_CNT_ACPI_EN BIT7 ///< ACPI eanble
+#define B_PCH_PMC_ACPI_CNT_SCIS (BIT2 | BIT1 | BIT0) ///< SCI IRQ select
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ9 0
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ10 1
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ11 2
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ20 4
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ21 5
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ22 6
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ23 7
+#define R_PCH_PMC_PWRM_BASE 0x48
+#define B_PCH_PMC_PWRM_BASE_BAR 0xFFFF0000 ///< PWRM must be 64KB alignment to align the source decode.
+#define R_PCH_PMC_GEN_PMCON_A 0xA0
+#define B_PCH_PMC_GEN_PMCON_A_DC_PP_DIS BIT30
+#define B_PCH_PMC_GEN_PMCON_A_DSX_PP_DIS BIT29
+#define B_PCH_PMC_GEN_PMCON_A_AG3_PP_EN BIT28
+#define B_PCH_PMC_GEN_PMCON_A_SX_PP_EN BIT27
+#define B_PCH_PMC_GEN_PMCON_A_DISB BIT23
+#define B_PCH_PMC_GEN_PMCON_A_MEM_SR BIT21
+#define B_PCH_PMC_GEN_PMCON_A_MS4V BIT18
+#define B_PCH_PMC_GEN_PMCON_A_GBL_RST_STS BIT16
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_OPI_PLL_SD_INC0 BIT13
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_SPXB_CG_INC0 BIT12
+#define B_PCH_PMC_GEN_PMCON_A_BIOS_PCI_EXP_EN BIT10
+#define B_PCH_PMC_GEN_PMCON_A_PWRBTN_LVL BIT9
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_C0 BIT7
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_OPI_ON BIT6
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_BCLKREQ_ON BIT5
+#define B_PCH_PMC_GEN_PMCON_A_SMI_LOCK BIT4
+#define B_PCH_PMC_GEN_PMCON_A_ESPI_SMI_LOCK BIT3 ///< ESPI SMI lock
+#define B_PCH_PMC_GEN_PMCON_A_PER_SMI_SEL 0x0003
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_64S 0x0000
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_32S 0x0001
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_16S 0x0002
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_8S 0x0003
+#define R_PCH_PMC_GEN_PMCON_B 0xA4
+#define B_PCH_PMC_GEN_PMCON_B_SLPSX_STR_POL_LOCK BIT18 ///< Lock down SLP_S3/SLP_S4 Minimum Assertion width
+#define B_PCH_PMC_GEN_PMCON_B_ACPI_BASE_LOCK BIT17 ///< Lock ACPI BASE at 0x40, only cleared by reset when set
+#define B_PCH_PMC_GEN_PMCON_B_PM_DATA_BAR_DIS BIT16
+#define B_PCH_PMC_GEN_PMCON_B_PME_B0_S5_DIS BIT15
+#define B_PCH_PMC_GEN_PMCON_B_SUS_PWR_FLR BIT14
+#define B_PCH_PMC_GEN_PMCON_B_WOL_EN_OVRD BIT13
+#define B_PCH_PMC_GEN_PMCON_B_DISABLE_SX_STRETCH BIT12
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW 0xC00
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_60US 0x000
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_1MS 0x400
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_50MS 0x800
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_2S 0xC00
+#define B_PCH_PMC_GEN_PMCON_B_HOST_RST_STS BIT9
+#define B_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL 0xC0
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_64MS 0xC0
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_32MS 0x80
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_16MS 0x40
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_1_5MS 0x00
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW 0x30
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_1S 0x30
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_2S 0x20
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_3S 0x10
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_4S 0x00
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S4_ASE BIT3
+#define B_PCH_PMC_GEN_PMCON_B_RTC_PWR_STS BIT2
+#define B_PCH_PMC_GEN_PMCON_B_PWR_FLR BIT1
+#define B_PCH_PMC_GEN_PMCON_B_AFTERG3_EN BIT0
+#define R_PCH_PMC_BM_CX_CNF 0xA8
+#define B_PCH_PMC_BM_CX_CNF_STORAGE_BREAK_EN BIT31
+#define B_PCH_PMC_BM_CX_CNF_PCIE_BREAK_EN BIT30
+#define B_PCH_PMC_BM_CX_CNF_AZ_BREAK_EN BIT24
+#define B_PCH_PMC_BM_CX_CNF_DPSN_BREAK_EN BIT19
+#define B_PCH_PMC_BM_CX_CNF_XHCI_BREAK_EN BIT17
+#define B_PCH_PMC_BM_CX_CNF_SATA3_BREAK_EN BIT16
+#define B_PCH_PMC_BM_CX_CNF_SCRATCHPAD BIT15
+#define B_PCH_PMC_BM_CX_CNF_PHOLD_BM_STS_BLOCK BIT14
+#define B_PCH_PMC_BM_CX_CNF_MASK_CF BIT11
+#define B_PCH_PMC_BM_CX_CNF_BM_STS_ZERO_EN BIT10
+#define B_PCH_PMC_BM_CX_CNF_PM_SYNC_MSG_MODE BIT9
+#define R_PCH_PMC_ETR3 0xAC
+#define B_PCH_PMC_ETR3_CF9LOCK BIT31 ///< CF9h Lockdown
+#define B_PCH_PMC_ETR3_USB_CACHE_DIS BIT21
+#define B_PCH_PMC_ETR3_CF9GR BIT20 ///< CF9h Global Reset
+#define B_PCH_PMC_ETR3_SKIP_HOST_RST_HS BIT19
+#define B_PCH_PMC_ETR3_CWORWRE BIT18
+
+//
+// ACPI and legacy I/O register offsets from ACPIBASE
+//
+#define R_PCH_ACPI_PM1_STS 0x00
+#define S_PCH_ACPI_PM1_STS 2
+#define B_PCH_ACPI_PM1_STS_WAK BIT15
+#define B_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS BIT14
+#define B_PCH_ACPI_PM1_STS_PRBTNOR BIT11
+#define B_PCH_ACPI_PM1_STS_RTC BIT10
+#define B_PCH_ACPI_PM1_STS_PWRBTN BIT8
+#define B_PCH_ACPI_PM1_STS_GBL BIT5
+#define B_PCH_ACPI_PM1_STS_BM BIT4
+#define B_PCH_ACPI_PM1_STS_TMROF BIT0
+#define N_PCH_ACPI_PM1_STS_WAK 15
+#define N_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS 14
+#define N_PCH_ACPI_PM1_STS_PRBTNOR 11
+#define N_PCH_ACPI_PM1_STS_RTC 10
+#define N_PCH_ACPI_PM1_STS_PWRBTN 8
+#define N_PCH_ACPI_PM1_STS_GBL 5
+#define N_PCH_ACPI_PM1_STS_BM 4
+#define N_PCH_ACPI_PM1_STS_TMROF 0
+
+#define R_PCH_ACPI_PM1_EN 0x02
+#define S_PCH_ACPI_PM1_EN 2
+#define B_PCH_ACPI_PM1_EN_PCIEXP_WAKE_DIS BIT14
+#define B_PCH_ACPI_PM1_EN_RTC BIT10
+#define B_PCH_ACPI_PM1_EN_PWRBTN BIT8
+#define B_PCH_ACPI_PM1_EN_GBL BIT5
+#define B_PCH_ACPI_PM1_EN_TMROF BIT0
+#define N_PCH_ACPI_PM1_EN_PCIEXP_WAKE_DIS 14
+#define N_PCH_ACPI_PM1_EN_RTC 10
+#define N_PCH_ACPI_PM1_EN_PWRBTN 8
+#define N_PCH_ACPI_PM1_EN_GBL 5
+#define N_PCH_ACPI_PM1_EN_TMROF 0
+
+#define R_PCH_ACPI_PM1_CNT 0x04
+#define S_PCH_ACPI_PM1_CNT 4
+#define B_PCH_ACPI_PM1_CNT_SLP_EN BIT13
+#define B_PCH_ACPI_PM1_CNT_SLP_TYP (BIT12 | BIT11 | BIT10)
+#define V_PCH_ACPI_PM1_CNT_S0 0
+#define V_PCH_ACPI_PM1_CNT_S1 BIT10
+#define V_PCH_ACPI_PM1_CNT_S3 (BIT12 | BIT10)
+#define V_PCH_ACPI_PM1_CNT_S4 (BIT12 | BIT11)
+#define V_PCH_ACPI_PM1_CNT_S5 (BIT12 | BIT11 | BIT10)
+#define B_PCH_ACPI_PM1_CNT_GBL_RLS BIT2
+#define B_PCH_ACPI_PM1_CNT_BM_RLD BIT1
+#define B_PCH_ACPI_PM1_CNT_SCI_EN BIT0
+
+#define R_PCH_ACPI_PM1_TMR 0x08
+#define V_PCH_ACPI_TMR_FREQUENCY 3579545
+#define B_PCH_ACPI_PM1_TMR_VAL 0xFFFFFF
+#define V_PCH_ACPI_PM1_TMR_MAX_VAL 0x1000000 ///< The timer is 24 bit overflow
+
+#define R_PCH_SMI_EN 0x30
+#define S_PCH_SMI_EN 4
+#define B_PCH_SMI_EN_LEGACY_USB3 BIT31
+#define B_PCH_SMI_EN_GPIO_UNLOCK_SMI BIT27
+#define B_PCH_SMI_EN_LEGACY_USB2 BIT17
+#define B_PCH_SMI_EN_PERIODIC BIT14
+#define B_PCH_SMI_EN_TCO BIT13
+#define B_PCH_SMI_EN_MCSMI BIT11
+#define B_PCH_SMI_EN_BIOS_RLS BIT7
+#define B_PCH_SMI_EN_SWSMI_TMR BIT6
+#define B_PCH_SMI_EN_APMC BIT5
+#define B_PCH_SMI_EN_ON_SLP_EN BIT4
+#define B_PCH_SMI_EN_LEGACY_USB BIT3
+#define B_PCH_SMI_EN_BIOS BIT2
+#define B_PCH_SMI_EN_EOS BIT1
+#define B_PCH_SMI_EN_GBL_SMI BIT0
+#define N_PCH_SMI_EN_LEGACY_USB3 31
+#define N_PCH_SMI_EN_ESPI 28
+#define N_PCH_SMI_EN_GPIO_UNLOCK 27
+#define N_PCH_SMI_EN_INTEL_USB2 18
+#define N_PCH_SMI_EN_LEGACY_USB2 17
+#define N_PCH_SMI_EN_PERIODIC 14
+#define N_PCH_SMI_EN_TCO 13
+#define N_PCH_SMI_EN_MCSMI 11
+#define N_PCH_SMI_EN_BIOS_RLS 7
+#define N_PCH_SMI_EN_SWSMI_TMR 6
+#define N_PCH_SMI_EN_APMC 5
+#define N_PCH_SMI_EN_ON_SLP_EN 4
+#define N_PCH_SMI_EN_LEGACY_USB 3
+#define N_PCH_SMI_EN_BIOS 2
+#define N_PCH_SMI_EN_EOS 1
+#define N_PCH_SMI_EN_GBL_SMI 0
+
+#define R_PCH_SMI_STS 0x34
+#define S_PCH_SMI_STS 4
+#define B_PCH_SMI_STS_LEGACY_USB3 BIT31
+#define B_PCH_SMI_STS_GPIO_UNLOCK BIT27
+#define B_PCH_SMI_STS_SPI BIT26
+#define B_PCH_SMI_STS_MONITOR BIT21
+#define B_PCH_SMI_STS_PCI_EXP BIT20
+#define B_PCH_SMI_STS_PATCH BIT19
+#define B_PCH_SMI_STS_INTEL_USB2 BIT18
+#define B_PCH_SMI_STS_LEGACY_USB2 BIT17
+#define B_PCH_SMI_STS_SMBUS BIT16
+#define B_PCH_SMI_STS_SERIRQ BIT15
+#define B_PCH_SMI_STS_PERIODIC BIT14
+#define B_PCH_SMI_STS_TCO BIT13
+#define B_PCH_SMI_STS_DEVMON BIT12
+#define B_PCH_SMI_STS_MCSMI BIT11
+#define B_PCH_SMI_STS_GPIO_SMI BIT10
+#define B_PCH_SMI_STS_GPE0 BIT9
+#define B_PCH_SMI_STS_PM1_STS_REG BIT8
+#define B_PCH_SMI_STS_SWSMI_TMR BIT6
+#define B_PCH_SMI_STS_APM BIT5
+#define B_PCH_SMI_STS_ON_SLP_EN BIT4
+#define B_PCH_SMI_STS_LEGACY_USB BIT3
+#define B_PCH_SMI_STS_BIOS BIT2
+#define N_PCH_SMI_STS_LEGACY_USB3 31
+#define N_PCH_SMI_STS_ESPI 28
+#define N_PCH_SMI_STS_GPIO_UNLOCK 27
+#define N_PCH_SMI_STS_SPI 26
+#define N_PCH_SMI_STS_MONITOR 21
+#define N_PCH_SMI_STS_PCI_EXP 20
+#define N_PCH_SMI_STS_PATCH 19
+#define N_PCH_SMI_STS_INTEL_USB2 18
+#define N_PCH_SMI_STS_LEGACY_USB2 17
+#define N_PCH_SMI_STS_SMBUS 16
+#define N_PCH_SMI_STS_SERIRQ 15
+#define N_PCH_SMI_STS_PERIODIC 14
+#define N_PCH_SMI_STS_TCO 13
+#define N_PCH_SMI_STS_DEVMON 12
+#define N_PCH_SMI_STS_MCSMI 11
+#define N_PCH_SMI_STS_GPIO_SMI 10
+#define N_PCH_SMI_STS_GPE0 9
+#define N_PCH_SMI_STS_PM1_STS_REG 8
+#define N_PCH_SMI_STS_SWSMI_TMR 6
+#define N_PCH_SMI_STS_APM 5
+#define N_PCH_SMI_STS_ON_SLP_EN 4
+#define N_PCH_SMI_STS_LEGACY_USB 3
+#define N_PCH_SMI_STS_BIOS 2
+
+#define R_PCH_ACPI_GPE_CNTL 0x40
+#define B_PCH_ACPI_GPE_CNTL_SWGPE_CTRL BIT17
+
+#define R_PCH_DEVACT_STS 0x44
+#define S_PCH_DEVACT_STS 2
+#define B_PCH_DEVACT_STS_MASK 0x13E1
+#define B_PCH_DEVACT_STS_KBC BIT12
+#define B_PCH_DEVACT_STS_PIRQDH BIT9
+#define B_PCH_DEVACT_STS_PIRQCG BIT8
+#define B_PCH_DEVACT_STS_PIRQBF BIT7
+#define B_PCH_DEVACT_STS_PIRQAE BIT6
+#define B_PCH_DEVACT_STS_D0_TRP BIT0
+#define N_PCH_DEVACT_STS_KBC 12
+#define N_PCH_DEVACT_STS_PIRQDH 9
+#define N_PCH_DEVACT_STS_PIRQCG 8
+#define N_PCH_DEVACT_STS_PIRQBF 7
+#define N_PCH_DEVACT_STS_PIRQAE 6
+
+#define R_PCH_ACPI_PM2_CNT 0x50
+#define B_PCH_ACPI_PM2_CNT_ARB_DIS BIT0
+
+#define R_PCH_OC_WDT_CTL 0x54
+#define B_PCH_OC_WDT_CTL_RLD BIT31
+#define B_PCH_OC_WDT_CTL_ICCSURV_STS BIT25
+#define B_PCH_OC_WDT_CTL_NO_ICCSURV_STS BIT24
+#define B_PCH_OC_WDT_CTL_FORCE_ALL BIT15
+#define B_PCH_OC_WDT_CTL_EN BIT14
+#define B_PCH_OC_WDT_CTL_ICCSURV BIT13
+#define B_PCH_OC_WDT_CTL_LCK BIT12
+#define B_PCH_OC_WDT_CTL_TOV_MASK 0x3FF
+#define B_PCH_OC_WDT_CTL_FAILURE_STS BIT23
+#define B_PCH_OC_WDT_CTL_UNXP_RESET_STS BIT22
+#define B_PCH_OC_WDT_CTL_AFTER_POST 0x3F0000
+#define V_PCH_OC_WDT_CTL_STATUS_FAILURE 1
+#define V_PCH_OC_WDT_CTL_STATUS_OK 0
+
+#define R_PCH_ACPI_GPE0_STS_31_0 0x80
+#define R_PCH_ACPI_GPE0_STS_63_32 0x84
+#define R_PCH_ACPI_GPE0_STS_95_64 0x88
+#define R_PCH_ACPI_GPE0_STS_127_96 0x8C
+#define S_PCH_ACPI_GPE0_STS_127_96 4
+#define B_PCH_ACPI_GPE0_STS_127_96_WADT BIT18
+#define B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE BIT16
+#define B_PCH_ACPI_GPE0_STS_127_96_PME_B0 BIT13
+#define B_PCH_ACPI_GPE0_STS_127_96_ME_SCI BIT12
+#define B_PCH_ACPI_GPE0_STS_127_96_PME BIT11
+#define B_PCH_ACPI_GPE0_STS_127_96_BATLOW BIT10
+#define B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP BIT9
+#define B_PCH_ACPI_GPE0_STS_127_96_RI BIT8
+#define B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK BIT7
+#define B_PCH_ACPI_GPE0_STS_127_96_TC0SCI BIT6
+#define B_PCH_ACPI_GPE0_STS_127_96_SWGPE BIT2
+#define B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG BIT1
+#define N_PCH_ACPI_GPE0_STS_127_96_PME_B0 13
+#define N_PCH_ACPI_GPE0_STS_127_96_PME 11
+#define N_PCH_ACPI_GPE0_STS_127_96_BATLOW 10
+#define N_PCH_ACPI_GPE0_STS_127_96_PCI_EXP 9
+#define N_PCH_ACPI_GPE0_STS_127_96_RI 8
+#define N_PCH_ACPI_GPE0_STS_127_96_SMB_WAK 7
+#define N_PCH_ACPI_GPE0_STS_127_96_TC0SCI 6
+#define N_PCH_ACPI_GPE0_STS_127_96_SWGPE 2
+#define N_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG 1
+
+#define R_PCH_ACPI_GPE0_EN_31_0 0x90
+#define R_PCH_ACPI_GPE0_EN_63_32 0x94
+#define R_PCH_ACPI_GPE0_EN_95_64 0x98
+#define R_PCH_ACPI_GPE0_EN_127_96 0x9C
+#define S_PCH_ACPI_GPE0_EN_127_96 4
+#define B_PCH_ACPI_GPE0_EN_127_96_WADT BIT18
+#define B_PCH_ACPI_GPE0_EN_127_96_LAN_WAKE BIT16
+#define B_PCH_ACPI_GPE0_EN_127_96_PME_B0 BIT13
+#define B_PCH_ACPI_GPE0_EN_127_96_ME_SCI BIT12
+#define B_PCH_ACPI_GPE0_EN_127_96_PME BIT11
+#define B_PCH_ACPI_GPE0_EN_127_96_BATLOW BIT10
+#define B_PCH_ACPI_GPE0_EN_127_96_PCI_EXP BIT9
+#define B_PCH_ACPI_GPE0_EN_127_96_RI BIT8
+#define B_PCH_ACPI_GPE0_EN_127_96_TC0SCI BIT6
+#define B_PCH_ACPI_GPE0_EN_127_96_SWGPE BIT2
+#define B_PCH_ACPI_GPE0_EN_127_96_HOT_PLUG BIT1
+#define N_PCH_ACPI_GPE0_EN_127_96_PME_B0 13
+#define N_PCH_ACPI_GPE0_EN_127_96_USB3 12
+#define N_PCH_ACPI_GPE0_EN_127_96_PME 11
+#define N_PCH_ACPI_GPE0_EN_127_96_BATLOW 10
+#define N_PCH_ACPI_GPE0_EN_127_96_PCI_EXP 9
+#define N_PCH_ACPI_GPE0_EN_127_96_RI 8
+#define N_PCH_ACPI_GPE0_EN_127_96_TC0SCI 6
+#define N_PCH_ACPI_GPE0_EN_127_96_SWGPE 2
+#define N_PCH_ACPI_GPE0_EN_127_96_HOT_PLUG 1
+
+
+//
+// TCO register I/O map
+//
+#define R_PCH_TCO_RLD 0x0
+#define R_PCH_TCO_DAT_IN 0x2
+#define R_PCH_TCO_DAT_OUT 0x3
+#define R_PCH_TCO1_STS 0x04
+#define S_PCH_TCO1_STS 2
+#define B_PCH_TCO1_STS_DMISERR BIT12
+#define B_PCH_TCO1_STS_DMISMI BIT10
+#define B_PCH_TCO1_STS_DMISCI BIT9
+#define B_PCH_TCO1_STS_BIOSWR BIT8
+#define B_PCH_TCO1_STS_NEWCENTURY BIT7
+#define B_PCH_TCO1_STS_TIMEOUT BIT3
+#define B_PCH_TCO1_STS_TCO_INT BIT2
+#define B_PCH_TCO1_STS_SW_TCO_SMI BIT1
+#define B_PCH_TCO1_STS_NMI2SMI BIT0
+#define N_PCH_TCO1_STS_DMISMI 10
+#define N_PCH_TCO1_STS_BIOSWR 8
+#define N_PCH_TCO1_STS_NEWCENTURY 7
+#define N_PCH_TCO1_STS_TIMEOUT 3
+#define N_PCH_TCO1_STS_SW_TCO_SMI 1
+#define N_PCH_TCO1_STS_NMI2SMI 0
+
+#define R_PCH_TCO2_STS 0x06
+#define S_PCH_TCO2_STS 2
+#define B_PCH_TCO2_STS_SMLINK_SLV_SMI BIT4
+#define B_PCH_TCO2_STS_BAD_BIOS BIT3
+#define B_PCH_TCO2_STS_BOOT BIT2
+#define B_PCH_TCO2_STS_SECOND_TO BIT1
+#define B_PCH_TCO2_STS_INTRD_DET BIT0
+#define N_PCH_TCO2_STS_INTRD_DET 0
+
+#define R_PCH_TCO1_CNT 0x08
+#define S_PCH_TCO1_CNT 2
+#define B_PCH_TCO_CNT_LOCK BIT12
+#define B_PCH_TCO_CNT_TMR_HLT BIT11
+#define B_PCH_TCO_CNT_NMI2SMI_EN BIT9
+#define B_PCH_TCO_CNT_NMI_NOW BIT8
+#define N_PCH_TCO_CNT_NMI2SMI_EN 9
+
+#define R_PCH_TCO2_CNT 0x0A
+#define S_PCH_TCO2_CNT 2
+#define B_PCH_TCO2_CNT_OS_POLICY 0x0030
+#define B_PCH_TCO2_CNT_GPI11_ALERT_DISABLE 0x0008
+#define B_PCH_TCO2_CNT_INTRD_SEL 0x0006
+#define N_PCH_TCO2_CNT_INTRD_SEL 2
+
+#define R_PCH_TCO_MESSAGE1 0x0C
+#define R_PCH_TCO_MESSAGE2 0x0D
+#define R_PCH_TCO_WDCNT 0x0E
+#define R_PCH_TCO_SW_IRQ_GEN 0x10
+#define B_PCH_TCO_IRQ12_CAUSE BIT1
+#define B_PCH_TCO_IRQ1_CAUSE BIT0
+#define R_PCH_TCO_TMR 0x12
+
+//
+// PWRM Registers
+//
+#define R_PCH_WADT_AC 0x0 ///< Wake Alarm Device Timer: AC
+#define R_PCH_WADT_DC 0x4 ///< Wake Alarm Device Timer: DC
+#define R_PCH_WADT_EXP_AC 0x8 ///< Wake Alarm Device Expired Timer: AC
+#define R_PCH_WADT_EXP_DC 0xC ///< Wake Alarm Device Expired Timer: DC
+#define R_PCH_PWRM_PRSTS 0x10 ///< Power and Reset Status
+#define B_PCH_PWRM_PRSTS_VE_WD_TMR_STS BIT7 ///< VE Watchdog Timer Status
+#define B_PCH_PWRM_PRSTS_WOL_OVR_WK_STS BIT5
+#define B_PCH_PWRM_PRSTS_FIELD_1 BIT4
+#define B_PCH_PWRM_PRSTS_ME_WAKE_STS BIT0
+#define R_PCH_PWRM_14 0x14
+#define R_PCH_PWRM_CFG 0x18 ///< Power Management Configuration
+#define B_PCH_PWRM_CFG_ALLOW_24_OSC_SD BIT29 ///< Allow 24MHz Crystal Oscillator Shutdown
+#define B_PCH_PWRM_CFG_ALLOW_USB2_CORE_PG BIT25 ///< Allow USB2 Core Power Gating
+#define B_PCH_PWRM_CFG_RTC_DS_WAKE_DIS BIT21 ///< RTC Wake from Deep S4/S5 Disable
+#define B_PCH_PWRM_CFG_SSMAW_MASK (BIT19 | BIT18) ///< SLP_SUS# Min Assertion Width
+#define V_PCH_PWRM_CFG_SSMAW_4S (BIT19 | BIT18) ///< 4 seconds
+#define V_PCH_PWRM_CFG_SSMAW_1S BIT19 ///< 1 second
+#define V_PCH_PWRM_CFG_SSMAW_0_5S BIT18 ///< 0.5 second (500ms)
+#define V_PCH_PWRM_CFG_SSMAW_0S 0 ///< 0 second
+#define B_PCH_PWRM_CFG_SAMAW_MASK (BIT17 | BIT16) ///< SLP_A# Min Assertion Width
+#define V_PCH_PWRM_CFG_SAMAW_2S (BIT17 | BIT16) ///< 2 seconds
+#define V_PCH_PWRM_CFG_SAMAW_98ms BIT17 ///< 98ms
+#define V_PCH_PWRM_CFG_SAMAW_4S BIT16 ///< 4 seconds
+#define V_PCH_PWRM_CFG_SAMAW_0S 0 ///< 0 second
+#define B_PCH_PWRM_CFG_RPCD_MASK (BIT9 | BIT8) ///< Reset Power Cycle Duration
+#define V_PCH_PWRM_CFG_RPCD_1S (BIT9 | BIT8) ///< 1-2 seconds
+#define V_PCH_PWRM_CFG_RPCD_2S BIT9 ///< 2-3 seconds
+#define V_PCH_PWRM_CFG_RPCD_3S BIT8 ///< 3-4 seconds
+#define V_PCH_PWRM_CFG_RPCD_4S 0 ///< 4-5 seconds (Default)
+#define R_PCH_PWRM_PCH_PM_STS 0x1C ///< Contains misc. fields used to record PCH power management events
+#define B_PCH_PWRM_PCH_PM_STS_PMC_MSG_FULL_STS BIT24 ///< MTPMC transport mechanism full indication
+#define R_PCH_PWRM_MTPMC 0x20 ///< Message to PMC
+#define V_PCH_PWRM_MTPMC_COMMAND_PG_LANE_0_15 0xE ///< Command to override lanes 0-15 power gating
+#define V_PCH_PWRM_MTPMC_COMMAND_PG_LANE_16_31 0xF ///< Command to override lanes 16-31 power gating
+#define B_PCH_PWRM_MTPMC_PG_CMD_DATA 0xFFFF0000 ///< Data part of PowerGate Message to PMC
+#define N_PCH_PWRM_MTPMC_PG_CMD_DATA 16
+#define R_PCH_PWRM_PCH_PM_STS2 0x24 ///< PCH Power Management Status
+#define R_PCH_PWRM_S3_PWRGATE_POL 0x28 ///< S3 Power Gating Policies
+#define B_PCH_PWRM_S3DC_GATE_SUS BIT1 ///< Deep S3 Enable in DC Mode
+#define B_PCH_PWRM_S3AC_GATE_SUS BIT0 ///< Deep S3 Enable in AC Mode
+#define R_PCH_PWRM_S4_PWRGATE_POL 0x2C ///< Deep S4 Power Policies
+#define B_PCH_PWRM_S4DC_GATE_SUS BIT1 ///< Deep S4 Enable in DC Mode
+#define B_PCH_PWRM_S4AC_GATE_SUS BIT0 ///< Deep S4 Enable in AC Mode
+#define R_PCH_PWRM_S5_PWRGATE_POL 0x30 ///< Deep S5 Power Policies
+#define B_PCH_PWRM_S5DC_GATE_SUS BIT15 ///< Deep S5 Enable in DC Mode
+#define B_PCH_PWRM_S5AC_GATE_SUS BIT14 ///< Deep S5 Enable in AC Mode
+#define R_PCH_PWRM_DSX_CFG 0x34 ///< Deep SX Configuration
+#define B_PCH_PWRM_DSX_CFG_WAKE_PIN_DSX_EN BIT2 ///< WAKE# Pin DeepSx Enable
+#define B_PCH_PWRM_DSX_CFG_ACPRES_PD_DSX_DIS BIT1 ///< AC_PRESENT pin pulldown in DeepSx disable
+#define B_PCH_PWRM_DSX_CFG_LAN_WAKE_EN BIT0 ///< LAN_WAKE Pin DeepSx Enable
+#define R_PCH_PWRM_CFG2 0x3C ///< Power Management Configuration Reg 2
+#define B_PCH_PWRM_CFG2_PBOP (BIT31 | BIT30 | BIT29) ///< Power Button Override Period (PBOP)
+#define N_PCH_PWRM_CFG2_PBOP 29 ///< Power Button Override Period (PBOP)
+#define B_PCH_PWRM_CFG2_PB_DIS BIT28 ///< Power Button Native Mode Disable (PB_DIS)
+#define B_PCH_PWRM_CFG2_DRAM_RESET_CTL BIT26 ///< DRAM RESET# control
+#define R_PCH_PWRM_EN_SN_SLOW_RING 0x48 ///< Enable Snoop Request to SLOW_RING
+#define R_PCH_PWRM_EN_SN_SLOW_RING2 0x4C ///< Enable Snoop Request to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_SN_SA 0x50 ///< Enable Snoop Request to SA
+#define R_PCH_PWRM_EN_SN_SA2 0x54 ///< Enable Snoop Request to SA 2nd Reg
+#define R_PCH_PWRM_EN_SN_SLOW_RING_CF 0x58 ///< Enable Snoop Request to SLOW_RING_CF
+#define R_PCH_PWRM_EN_NS_SA 0x68 ///< Enable Non-Snoop Request to SA
+#define R_PCH_PWRM_EN_CW_SLOW_RING 0x80 ///< Enable Clock Wake to SLOW_RING
+#define R_PCH_PWRM_EN_CW_SLOW_RING2 0x84 ///< Enable Clock Wake to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_CW_SA 0x88 ///< Enable Clock Wake to SA
+#define R_PCH_PWRM_EN_CW_SA2 0x8C ///< Enable Clock Wake to SA 2nd Reg
+#define R_PCH_PWRM_EN_CW_SLOW_RING_CF 0x98 ///< Enable Clock Wake to SLOW_RING_CF
+#define R_PCH_PWRM_EN_PA_SLOW_RING 0xA8 ///< Enable Pegged Active to SLOW_RING
+#define R_PCH_PWRM_EN_PA_SLOW_RING2 0xAC ///< Enable Pegged Active to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_PA_SA 0xB0 ///< Enable Pegged Active to SA
+#define R_PCH_PWRM_EN_PA_SA2 0xB4 ///< Enable Pegged Active to SA 2nd Reg
+#define R_PCH_PWRM_EN_MISC_EVENT 0xC0 ///< Enable Misc PM_SYNC Events
+#define R_PCH_PWRM_PMSYNC_TPR_CONFIG 0xC4
+#define B_PCH_PWRM_PMSYNC_TPR_CONFIG_LOCK BIT31
+#define B_PCH_PWRM_PMSYNC_PCH2CPU_TT_EN BIT26
+#define B_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE (BIT25 | BIT24)
+#define N_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE 24
+#define V_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE_1 1
+#define R_PCH_PWRM_PMSYNC_MISC_CFG 0xC8
+#define B_PCH_PWRM_PMSYNC_PM_SYNC_LOCK BIT15 ///< PM_SYNC Configuration Lock
+#define B_PCH_PWRM_PMSYNC_GPIO_D_SEL BIT11
+#define B_PCH_PWRM_PMSYNC_GPIO_C_SEL BIT10
+#define R_PCH_PWRM_PM_SYNC_STATE_HYS 0xD0 ///< PM_SYNC State Hysteresis
+#define R_PCH_PWRM_PM_SYNC_MODE 0xD4 ///< PM_SYNC Pin Mode
+#define R_PCH_PWRM_CFG3 0xE0 ///< Power Management Configuration Reg 3
+#define B_PCH_PWRM_CFG3_DSX_WLAN_PP_EN BIT16 ///< Deep-Sx WLAN Phy Power Enable
+#define B_PCH_PWRM_CFG3_HOST_WLAN_PP_EN BIT17 ///< Host Wireless LAN Phy Power Enable
+#define B_PCH_PWRM_CFG3_PWRG_LOCK BIT2 ///< Lock power gating override messages
+#define R_PCH_PWRM_PM_DOWN_PPB_CFG 0xE4 ///< PM_DOWN PCH_POWER_BUDGET CONFIGURATION
+#define R_PCH_PWRM_CFG4 0xE8 ///< Power Management Configuration Reg 4
+#define B_PCH_PWRM_CFG4_U2_PHY_PG_EN BIT30 ///< USB2 PHY SUS Well Power Gating Enable
+#define B_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR (0x000001FF) ///< CPU I/O VR Ramp Duration, [8:0]
+#define N_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR 0
+#define V_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR_70US 0x007
+#define V_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR_240US 0x018
+#define R_PCH_PWRM_CPU_EPOC 0xEC
+#define R_PCH_PWRM_VR_MISC_CTL 0x100
+#define B_PCH_PWRM_VR_MISC_CTL_VIDSOVEN BIT3
+#define R_PCH_PWRM_GPIO_CFG 0x120
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW2 (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW2 8
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW1 (BIT7 | BIT6 | BIT5 | BIT4)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW1 4
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW0 (BIT3 | BIT2 | BIT1 | BIT0)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW0 0
+#define R_PCH_PWRM_PM_SYNC_MODE_C0 0xF4 ///< PM_SYNC Pin Mode in C0
+#define R_PCH_PWRM_ACPI_TMR_CTL 0xFC
+#define B_PCH_PWRM_ACPI_TMR_DIS BIT1
+#define R_PCH_PWRM_124 0x124
+#define R_PCH_PWRM_SLP_S0_RESIDENCY_COUNTER 0x13C
+#define R_PCH_PWRM_MODPHY_PM_CFG1 0x200
+#define R_PCH_PWRM_MODPHY_PM_CFG1_MLSXSWPGP 0xFFFF
+#define R_PCH_PWRM_MODPHY_PM_CFG2 0x204 ///< ModPHY Power Management Configuration Reg 2
+#define B_PCH_PWRM_MODPHY_PM_CFG2_MLSPDDGE BIT30 ///< ModPHY Lane SUS Power Domain Dynamic Gating Enable
+#define B_PCH_PWRM_MODPHY_PM_CFG2_EMFC BIT29 ///< Enable ModPHY FET Control
+#define B_PCH_PWRM_MODPHY_PM_CFG2_EFRT (BIT28 | BIT27 | BIT26 | BIT25 | BIT24) ///< External FET Ramp Time
+#define N_PCH_PWRM_MODPHY_PM_CFG2_EFRT 24
+#define V_PCH_PWRM_MODPHY_PM_CFG2_EFRT_200US 0x0A
+#define B_PCH_PWRM_MODPHY_PM_CFG2_ASLOR_UFS BIT16 ///< UFS ModPHY SPD SPD Override
+#define R_PCH_PWRM_MODPHY_PM_CFG3 0x208 ///< ModPHY Power Management Configuration Reg 3
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_UFS BIT16 ///< UFS ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_XDCI BIT15 ///< xDCI ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_XHCI BIT14 ///< xHCI ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_GBE BIT13 ///< GbE ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_SATA BIT12 ///< SATA ModPHY SPD RT Request
+#define R_PCH_PWRM_30C 0x30C
+#define R_PCH_PWRM_OBFF_CFG 0x314 ///< OBFF Configuration
+#define R_PCH_PWRM_31C 0x31C
+#define R_PCH_PWRM_CPPM_MISC_CFG 0x320 ///< CPPM Miscellaneous Configuration
+#define R_PCH_PWRM_CPPM_CG_POL1A 0x324 ///< CPPM Clock Gating Policy Reg 1
+#define R_PCH_PWRM_CPPM_CG_POL2A 0x340 ///< CPPM Clock Gating Policy Reg 3
+#define R_PCH_PWRM_34C 0x34C
+#define R_PCH_PWRM_CPPM_CG_POL3A 0x3A8 ///< CPPM Clock Gating Policy Reg 5
+#define B_PCH_PWRM_CPPM_CG_POLXA_CPPM_GX_QUAL BIT30 ///< CPPM Shutdown Qualifier Enable for Clock Source Group X
+#define B_PCH_PWRM_CPPM_CG_POLXA_LTR_GX_THRESH (0x000001FF) ///< LTR Threshold for Clock Source Group X, [8:0]
+#define R_PCH_PWRM_3D0 0x3D0
+#define R_PCH_PWRM_CPPM_MPG_POL1A 0x3E0 ///< CPPM ModPHY Gating Policy Reg 1A
+#define B_PCH_PWRM_CPPM_MPG_POL1A_CPPM_MODPHY_QUAL BIT30 ///< CPPM Shutdown Qualifier Enable for ModPHY
+#define B_PCH_PWRM_CPPM_MPG_POL1A_LT_MODPHY_SEL BIT29 ///< ASLT/PLT Selection for ModPHY
+#define B_PCH_PWRM_CPPM_MPG_POL1A_LTR_MODPHY_THRESH (0x000001FF) ///< LTR Threshold for ModPHY, [8:0]
+#define R_PCH_PWRM_CS_SD_CTL1 0x3E8 ///< Clock Source Shutdown Control Reg 1
+#define B_PCH_PWRM_CS_SD_CTL1_CS5_CTL_CFG (BIT22 | BIT21 | BIT20) ///< Clock Source 5 Control Configuration
+#define N_PCH_PWRM_CS_SD_CTL1_CS5_CTL_CFG 20
+#define B_PCH_PWRM_CS_SD_CTL1_CS1_CTL_CFG (BIT2 | BIT1 | BIT0) ///< Clock Source 1 Control Configuration
+#define N_PCH_PWRM_CS_SD_CTL1_CS1_CTL_CFG 0
+#define R_PCH_PWRM_CS_SD_CTL2 0x3EC ///< Clock Source Shutdown Control Reg 2
+#define R_PCH_PWRM_HSWPGCR1 0x5D0
+#define B_PCH_PWRM_SW_PG_CTRL_LOCK BIT31
+#define B_PCH_PWRM_DFX_SW_PG_CTRL BIT0
+#define R_PCH_PWRM_600 0x600
+#define R_PCH_PWRM_604 0x604
+#define R_PCH_PWRM_ST_PG_FDIS_PMC_1 0x620 ///< Static PG Related Function Disable Register 1
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK BIT31 ///< Static Function Disable Lock (ST_FDIS_LK)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_CAM_FDIS_PMC BIT6 ///< Camera Function Disable (PMC Version) (CAM_FDIS_PMC)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_ISH_FDIS_PMC BIT5 ///< SH Function Disable (PMC Version) (ISH_FDIS_PMC)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_GBE_FDIS_PMC BIT0 ///< GBE Function Disable (PMC Version) (GBE_FDIS_PMC)
+#define R_PCH_PWRM_ST_PG_FDIS_PMC_2 0x624 ///< Static Function Disable Control Register 2
+#define V_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_FDIS_PMC 0x7FF ///< Static Function Disable Control Register 2
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_GSPI1_FDIS_PMC BIT10 ///< SerialIo Controller GSPI Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_GSPI0_FDIS_PMC BIT9 ///< SerialIo Controller GSPI Device 0 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART2_FDIS_PMC BIT8 ///< SerialIo Controller UART Device 2 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART1_FDIS_PMC BIT7 ///< SerialIo Controller UART Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART0_FDIS_PMC BIT6 ///< SerialIo Controller UART Device 0 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C5_FDIS_PMC BIT5 ///< SerialIo Controller I2C Device 5 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C4_FDIS_PMC BIT4 ///< SerialIo Controller I2C Device 4 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C3_FDIS_PMC BIT3 ///< SerialIo Controller I2C Device 3 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C2_FDIS_PMC BIT2 ///< SerialIo Controller I2C Device 2 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C1_FDIS_PMC BIT1 ///< SerialIo Controller I2C Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C0_FDIS_PMC BIT0 ///< SerialIo Controller I2C Device 0 Function Disable
+#define R_PCH_PWRM_NST_PG_FDIS_1 0x628
+#define B_PCH_PWRM_NST_PG_FDIS_1_SCC_FDIS_PMC BIT25 ///< SCC Function Disable. This is only avaiable in B0 onward.
+#define B_PCH_PWRM_NST_PG_FDIS_1_XDCI_FDIS_PMC BIT24 ///< XDCI Function Disable. This is only avaiable in B0 onward.
+#define B_PCH_PWRM_NST_PG_FDIS_1_ADSP_FDIS_PMC BIT23 ///< ADSP Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_SATA_FDIS_PMC BIT22 ///< SATA Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C3_FDIS_PMC BIT13 ///< PCIe Controller C Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C2_FDIS_PMC BIT12 ///< PCIe Controller C Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C1_FDIS_PMC BIT11 ///< PCIe Controller C Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C0_FDIS_PMC BIT10 ///< PCIe Controller C Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B3_FDIS_PMC BIT9 ///< PCIe Controller B Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B2_FDIS_PMC BIT8 ///< PCIe Controller B Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B1_FDIS_PMC BIT7 ///< PCIe Controller B Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B0_FDIS_PMC BIT6 ///< PCIe Controller B Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A3_FDIS_PMC BIT5 ///< PCIe Controller A Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A2_FDIS_PMC BIT4 ///< PCIe Controller A Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A1_FDIS_PMC BIT3 ///< PCIe Controller A Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A0_FDIS_PMC BIT2 ///< PCIe Controller A Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_XHCI_FDIS_PMC BIT0 ///< XHCI Function Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_1 0x640 ///< Fuse Disable Read 1 Register
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E3_FUSE_DIS BIT21 ///< PCIe Controller E Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E2_FUSE_DIS BIT20 ///< PCIe Controller E Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E1_FUSE_DIS BIT19 ///< PCIe Controller E Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E0_FUSE_DIS BIT18 ///< PCIe Controller E Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D3_FUSE_DIS BIT17 ///< PCIe Controller D Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D2_FUSE_DIS BIT16 ///< PCIe Controller D Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D1_FUSE_DIS BIT15 ///< PCIe Controller D Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D0_FUSE_DIS BIT14 ///< PCIe Controller D Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C3_FUSE_DIS BIT13 ///< PCIe Controller C Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C2_FUSE_DIS BIT12 ///< PCIe Controller C Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C1_FUSE_DIS BIT11 ///< PCIe Controller C Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C0_FUSE_DIS BIT10 ///< PCIe Controller C Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B3_FUSE_DIS BIT9 ///< PCIe Controller B Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B2_FUSE_DIS BIT8 ///< PCIe Controller B Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B1_FUSE_DIS BIT7 ///< PCIe Controller B Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B0_FUSE_DIS BIT6 ///< PCIe Controller B Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A3_FUSE_DIS BIT5 ///< PCIe Controller A Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A2_FUSE_DIS BIT4 ///< PCIe Controller A Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A1_FUSE_DIS BIT3 ///< PCIe Controller A Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A0_FUSE_DIS BIT2 ///< PCIe Controller A Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_XHCI_FUSE_DIS BIT0 ///< XHCI Fuse Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_2 0x644 ///< Fuse Disable Read 2 Register
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPC_SS_DIS BIT25 ///< SPC Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPB_SS_DIS BIT24 ///< SPB Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPA_SS_DIS BIT23 ///< SPA Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_PSTH_FUSE_SS_DIS BIT21 ///< PSTH Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_DMI_FUSE_SS_DIS BIT20 ///< DMI Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_OTG_FUSE_SS_DIS BIT19 ///< OTG Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_XHCI_SS_DIS BIT18 ///< XHCI Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_FIA_FUSE_SS_DIS BIT17 ///< FIA Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_DSP_FUSE_SS_DIS BIT16 ///< DSP Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SATA_FUSE_SS_DIS BIT15 ///< SATA Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ICC_FUSE_SS_DIS BIT14 ///< ICC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_LPC_FUSE_SS_DIS BIT13 ///< LPC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_RTC_FUSE_SS_DIS BIT12 ///< RTC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_P2S_FUSE_SS_DIS BIT11 ///< P2S Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_TRSB_FUSE_SS_DIS BIT10 ///< TRSB Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SMB_FUSE_SS_DIS BIT9 ///< SMB Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ITSS_FUSE_SS_DIS BIT8 ///< ITSS Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SERIALIO_FUSE_SS_DIS BIT6 ///< SerialIo Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SCC_FUSE_SS_DIS BIT4 ///< SCC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_P2D_FUSE_SS_DIS BIT3 ///< P2D Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_CAM_FUSE_SS_DIS BIT2 ///< Camera Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ISH_FUSE_SS_DIS BIT1 ///< ISH Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS BIT0 ///< GBE Fuse or Soft Strap Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_3 0x648 ///< Static PG Fuse and Soft Strap Disable Read Register 3
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA3_FUSE_SS_DIS BIT3 ///< PNCRA3 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA2_FUSE_SS_DIS BIT2 ///< PNCRA2 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA1_FUSE_SS_DIS BIT1 ///< PNCRA1 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA_FUSE_SS_DIS BIT0 ///< PNCRA Fuse or Soft Strap Disable
+
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h
new file mode 100644
index 0000000000..c52f1e721d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h
@@ -0,0 +1,364 @@
+/** @file
+ Register definition for PSF component
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_PSF_H_
+#define _PCH_REGS_PSF_H_
+
+//
+// Private chipset regsiter (Memory space) offset definition
+// The PCR register defines is used for PCR MMIO programming and PCH SBI programming as well.
+//
+
+//
+// PSFx segment registers
+//
+#define R_PCH_PCR_PSF_GLOBAL_CONFIG 0x4000 ///< PSF Segment Global Configuration Register
+#define B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG BIT4
+#define B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG BIT3
+#define R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0 0x4010 ///< PSF Segment Rootspace Configuration Register
+#define R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS1 0x4014
+#define B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P BIT1
+#define B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_VTDEN BIT0
+#define R_PCH_PCR_PSF_PORT_CONFIG_PG0_PORT0 0x4018 ///< PSF Segment Port Configuration Register
+
+#define S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR 4
+#define S_PCH_PSF_TARGET_GNTCNT_RELOAD 4
+#define B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD 0x1F
+#define B_PCH_PSF_TARGET_GNTCNT_RELOAD_GNT_CNT_RELOAD 0x1F
+
+//
+// PSFx PCRs definitions
+//
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR0 0 ///< PCI BAR0
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR1 0x04 ///< PCI BAR1
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR2 0x08 ///< PCI BAR2
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR3 0x0C ///< PCI BAR3
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR4 0x10 ///< PCI BAR4
+#define R_PCH_PCR_PSFX_T0_SHDW_PCIEN 0x1C ///< PCI configuration space enable bits
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR0DIS BIT16 ///< Disable BAR0
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR1DIS BIT17 ///< Disable BAR1
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS BIT18 ///< Disable BAR2
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS BIT19 ///< Disable BAR3
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR4DIS BIT20 ///< Disable BAR4
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR5DIS BIT21 ///< Disable BAR5
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS BIT8 ///< Function disable
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_MEMEN BIT1 ///< Memory decoding enable
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_IOEN BIT0 ///< IO decoding enable
+#define R_PCH_PCR_PSFX_T0_SHDW_PMCSR 0x20 ///< PCI power management configuration
+#define B_PCH_PCR_PSFX_T0_SHDW_PMCSR_PWRST (BIT1 | BIT0) ///< Power status
+#define R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS 0x38 ///< PCI configuration disable
+#define B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS BIT0 ///< config disable
+
+#define R_PCH_PCR_PSFX_T1_SHDW_PCIEN 0x3C ///< PCI configuration space enable bits
+#define B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS BIT8 ///< Function disable
+#define B_PCH_PCR_PSFX_T1_SHDW_PCIEN_MEMEN BIT1 ///< Memory decoding enable
+#define B_PCH_PCR_PSFX_T1_SHDW_PCIEN_IOEN BIT0 ///< IO decoding enable
+
+#define B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE 0x01F0 ///< device number
+#define N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE 4
+#define B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION (BIT3 | BIT2 | BIT1) ///< function number
+#define N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION 1
+
+#define V_PCH_LP_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB 0x38A00
+#define V_PCH_H_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB 0x38B00
+
+//
+// PSF1 PCRs
+//
+// PSF1 PCH-LP Specific Base Address
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_GBE_REG_BASE 0x0200 ///< D31F6 PSF base address (GBE)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE 0x0300 ///< D20F3 PSF base address (CAM)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CSE_WLAN_REG_BASE 0x0500 ///< D22F7 PSF base address (CSME: WLAN)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_HECI3_REG_BASE 0x0700 ///< D22F4 PSF base address (CSME: HECI3)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_HECI2_REG_BASE 0x0800 ///< D22F1 PSF base address (CSME: HECI2)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CSE_UMA_REG_BASE 0x0900 ///< D18F3 PSF base address (CSME: CSE UMA)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_HECI1_REG_BASE 0x0A00 ///< D22F0 PSF base address (CSME: HECI1)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_KT_REG_BASE 0x0B00 ///< D22F3 PSF base address (CSME: KT)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_IDER_REG_BASE 0x0C00 ///< D22F2 PSF base address (CSME: IDER)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CLINK_REG_BASE 0x0D00 ///< D18F1 PSF base address (CSME: CLINK)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_PMT_REG_BASE 0x0E00 ///< D18F2 PSF base address (CSME: PMT)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_KVM_REG_BASE 0x0F00 ///< D18F0 PSF base address (CSME: KVM)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_SATA_REG_BASE 0x1000 ///< PCH-LP D23F0 PSF base address (SATA)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE12_REG_BASE 0x2000 ///< PCH-LP D29F3 PSF base address (PCIE PORT 12)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE11_REG_BASE 0x2100 ///< PCH-LP D29F2 PSF base address (PCIE PORT 11)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE10_REG_BASE 0x2200 ///< PCH-LP D29F1 PSF base address (PCIE PORT 10)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE09_REG_BASE 0x2300 ///< PCH-LP D29F0 PSF base address (PCIE PORT 09)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE08_REG_BASE 0x2400 ///< PCH-LP D28F7 PSF base address (PCIE PORT 08)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE07_REG_BASE 0x2500 ///< PCH-LP D28F6 PSF base address (PCIE PORT 07)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE06_REG_BASE 0x2600 ///< PCH-LP D28F5 PSF base address (PCIE PORT 06)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE05_REG_BASE 0x2700 ///< PCH-LP D28F4 PSF base address (PCIE PORT 05)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE04_REG_BASE 0x2800 ///< PCH-LP D28F3 PSF base address (PCIE PORT 04)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE03_REG_BASE 0x2900 ///< PCH-LP D28F2 PSF base address (PCIE PORT 03)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE02_REG_BASE 0x2A00 ///< PCH-LP D28F1 PSF base address (PCIE PORT 02)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE 0x2B00 ///< PCH-LP D28F0 PSF base address (PCIE PORT 01)
+
+// PSF1 PCH-H Specific Base Address
+#define R_PCH_H_PCR_PSF1_T0_SHDW_CSE_WLAN_REG_BASE 0x0200 ///< D22F7 PSF base address (CSME: WLAN)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_HECI3_REG_BASE 0x0300 ///< SPT-H D22F4 PSF base address (CSME: HECI3)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_HECI2_REG_BASE 0x0400 ///< SPT-H D22F1 PSF base address (CSME: HECI2)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_CSE_UMA_REG_BASE 0x0500 ///< D18F3 PSF base address (CSME: CSE UMA)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_HECI1_REG_BASE 0x0600 ///< SPT-H D22F0 PSF base address (CSME: HECI1)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_KT_REG_BASE 0x0700 ///< SPT-H D22F3 PSF base address (CSME: KT)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_IDER_REG_BASE 0x0800 ///< SPT-H D22F2 PSF base address (CSME: IDER)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_CLINK_REG_BASE 0x0900 ///< D18F1 PSF base address (CSME: CLINK)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_PMT_REG_BASE 0x0A00 ///< D18F2 PSF base address (CSME: PMT)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_KVM_REG_BASE 0x0B00 ///< D18F0 PSF base address (CSME: KVM)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_SATA_REG_BASE 0x0C00 ///< PCH-H D23F0 PSF base address (SATA)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE20_REG_BASE 0x2000 ///< PCH-H D27F3 PSF base address (PCIE PORT 20)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE19_REG_BASE 0x2100 ///< PCH-H D27F2 PSF base address (PCIE PORT 19)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE18_REG_BASE 0x2200 ///< PCH-H D27F1 PSF base address (PCIE PORT 18)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE17_REG_BASE 0x2300 ///< PCH-H D27F0 PSF base address (PCIE PORT 17)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE16_REG_BASE 0x2400 ///< PCH-H D29F7 PSF base address (PCIE PORT 16)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE15_REG_BASE 0x2500 ///< PCH-H D29F6 PSF base address (PCIE PORT 15)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE14_REG_BASE 0x2600 ///< PCH-H D29F5 PSF base address (PCIE PORT 14)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE13_REG_BASE 0x2700 ///< PCH-H D29F4 PSF base address (PCIE PORT 13)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE12_REG_BASE 0x2800 ///< PCH-H D29F3 PSF base address (PCIE PORT 10)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE11_REG_BASE 0x2900 ///< PCH-H D29F2 PSF base address (PCIE PORT 11)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE10_REG_BASE 0x2A00 ///< PCH-H D29F1 PSF base address (PCIE PORT 10)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE09_REG_BASE 0x2B00 ///< PCH-H D29F0 PSF base address (PCIE PORT 09)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE08_REG_BASE 0x2C00 ///< PCH-H D28F7 PSF base address (PCIE PORT 08)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE07_REG_BASE 0x2D00 ///< PCH-H D28F6 PSF base address (PCIE PORT 07)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE06_REG_BASE 0x2E00 ///< PCH-H D28F5 PSF base address (PCIE PORT 06)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE05_REG_BASE 0x2F00 ///< PCH-H D28F4 PSF base address (PCIE PORT 05)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE04_REG_BASE 0x3000 ///< PCH-H D28F3 PSF base address (PCIE PORT 04)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE03_REG_BASE 0x3100 ///< PCH-H D28F2 PSF base address (PCIE PORT 03)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE02_REG_BASE 0x3200 ///< PCH-H D28F1 PSF base address (PCIE PORT 02)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE 0x3300 ///< PCH-H D28F0 PSF base address (PCIE PORT 01)
+
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE24_REG_BASE 0x2000 ///< PCH-H D27F7 PSF base address (PCIE PORT 24)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE23_REG_BASE 0x2100 ///< PCH-H D27F6 PSF base address (PCIE PORT 23)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE22_REG_BASE 0x2200 ///< PCH-H D27F5 PSF base address (PCIE PORT 22)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE21_REG_BASE 0x2300 ///< PCH-H D27F4 PSF base address (PCIE PORT 21)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE20_REG_BASE 0x2400 ///< PCH-H D27F3 PSF base address (PCIE PORT 20)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE19_REG_BASE 0x2500 ///< PCH-H D27F2 PSF base address (PCIE PORT 19)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE18_REG_BASE 0x2600 ///< PCH-H D27F1 PSF base address (PCIE PORT 18)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE17_REG_BASE 0x2700 ///< PCH-H D27F0 PSF base address (PCIE PORT 17)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE16_REG_BASE 0x2800 ///< PCH-H D29F7 PSF base address (PCIE PORT 16)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE15_REG_BASE 0x2900 ///< PCH-H D29F6 PSF base address (PCIE PORT 15)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE14_REG_BASE 0x2A00 ///< PCH-H D29F5 PSF base address (PCIE PORT 14)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE13_REG_BASE 0x2B00 ///< PCH-H D29F4 PSF base address (PCIE PORT 13)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE12_REG_BASE 0x2C00 ///< PCH-H D29F3 PSF base address (PCIE PORT 10)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE11_REG_BASE 0x2D00 ///< PCH-H D29F2 PSF base address (PCIE PORT 11)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE10_REG_BASE 0x2E00 ///< PCH-H D29F1 PSF base address (PCIE PORT 10)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE09_REG_BASE 0x2F00 ///< PCH-H D29F0 PSF base address (PCIE PORT 09)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE08_REG_BASE 0x3000 ///< PCH-H D28F7 PSF base address (PCIE PORT 08)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE07_REG_BASE 0x3100 ///< PCH-H D28F6 PSF base address (PCIE PORT 07)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE06_REG_BASE 0x3200 ///< PCH-H D28F5 PSF base address (PCIE PORT 06)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE05_REG_BASE 0x3300 ///< PCH-H D28F4 PSF base address (PCIE PORT 05)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE04_REG_BASE 0x3400 ///< PCH-H D28F3 PSF base address (PCIE PORT 04)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE03_REG_BASE 0x3500 ///< PCH-H D28F2 PSF base address (PCIE PORT 03)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE02_REG_BASE 0x3600 ///< PCH-H D28F1 PSF base address (PCIE PORT 02)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE 0x3700 ///< PCH-H D28F0 PSF base address (PCIE PORT 01)
+
+
+// Other PSF1 PCRs definition
+#define R_PCH_H_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7 0x4038 ///< PSF Port Configuration Register
+#define R_PCH_LP_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7 0x403C ///< PSF Port Configuration Register
+#define R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI 0x4050 ///< Multicast Control Register
+#define R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x4060 ///< Destination ID
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI 0x4048 ///< Multicast Control Register
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x4058 ///< Destination ID
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI 0x404C ///< Multicast Control Register
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x405C ///< Destination ID
+
+
+//PSF 1 Multicast Message Configuration
+
+#define R_PCH_PCR_PSF1_RC_OWNER_RS0 0x4008 ///< Destination ID
+
+#define B_PCH_PCR_PSF1_TARGET_CHANNELID 0xFF
+#define B_PCH_PCR_PSF1_TARGET_PORTID 0x7F00
+#define N_PCH_PCR_PSF1_TARGET_PORTID 8
+#define B_PCH_PCR_PSF1_TARGET_PORTGROUPID BIT15
+#define N_PCH_PCR_PSF1_TARGET_PORTGROUPID 15
+#define B_PCH_PCR_PSF1_TARGET_PSFID 0xFF0000
+#define N_PCH_PCR_PSF1_TARGET_PSFID 16
+#define B_PCH_PCR_PSF1_TARGET_CHANMAP BIT31
+
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_CHANNELID 0
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PORTID 10
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PORTGROUPID_DOWNSTREAM 1
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PSFID_PMT 0
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PSFID_PSF1 1
+
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PORTGROUPID_UPSTREAM 0
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PORTGROUPID_DOWNSTREAM 1
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PSFID_PSF1 1
+
+#define R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1 0x4058 ///< Multicast Control Register
+#define R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGT0_MCTP1 0x409C ///< Destination ID
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1 0x4050 ///< Multicast Control Register
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGT0_MCTP1 0x40B4 ///< Destination ID
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1 0x4054 ///< Multicast Control Register
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGT0_MCTP1 0x40C8 ///< Destination ID
+
+#define B_PCH_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1_MULTCEN BIT0
+#define B_PCH_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1_NUMMC 0xFE
+#define N_PCH_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1_NUMMC 1
+
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_CHANNELID_DMI 0
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PORTID_DMI 0
+
+
+
+//
+// controls the PCI configuration header of a PCI function
+//
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0 0x4198 ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F1 0x419C ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F2 0x41A0 ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F3 0x41A4 ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F4 0x41A8 ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F5 0x41AC ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F6 0x41B0 ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F7 0x41B4 ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F0 0x41B8 ///< SPC
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F1 0x41BC ///< SPC
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F2 0x41C0 ///< SPC
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F3 0x41C4 ///< SPC
+
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0 0x41C0 ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F1 0x41C4 ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F2 0x41C8 ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F3 0x41CC ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F4 0x41D0 ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F5 0x41D4 ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F6 0x41D8 ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F7 0x41DC ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F0 0x41E0 ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F1 0x41E4 ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F2 0x41E8 ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F3 0x41EC ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F4 0x41F0 ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F5 0x41F4 ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F6 0x41F8 ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F7 0x41FC ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F0 0x4200 ///< SPE
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F1 0x4204 ///< SPE
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F2 0x4208 ///< SPE
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F3 0x420C ///< SPE
+
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0 0x4274 ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F1 0x4278 ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F2 0x427C ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F3 0x4280 ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F4 0x4284 ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F5 0x4288 ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F6 0x428C ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F7 0x4290 ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F0 0x4294 ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F1 0x4298 ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F2 0x429C ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F3 0x42A0 ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F4 0x42A4 ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F5 0x42A8 ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F6 0x42AC ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F7 0x42B0 ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F0 0x42B4 ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F1 0x42B8 ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F2 0x42BC ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F3 0x42C0 ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F4 0x42C4 ///< SPF
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F5 0x42C8 ///< SPF
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F6 0x42CC ///< SPF
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F7 0x42D0 ///< SPF
+
+//
+// PSF1 grant count registers
+//
+#define R_PCH_LP_PSF1_DEV_GNTCNT_RELOAD_DGCR0 0x41CC
+#define R_PCH_LP_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0 0x45D0
+
+#define R_SKL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0 0x4214
+#define R_KBL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0 0x42D8
+#define R_SKL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0 0x46DC
+#define R_KBL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0 0x4834
+
+//
+// PSF2 PCRs (PID:PSF2)
+//
+#define R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE 0x0100 ///< D20F2 PSF base address (Thermal). // LP&H
+// PSF2 PCH-LP Specific Base Address
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_UFS_REG_BASE 0x0200 ///< D30F7 PSF base address (SCC: UFS)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_SDCARD_REG_BASE 0x0300 ///< D30F6 PSF base address (SCC: SDCard)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_SDIO_REG_BASE 0x0400 ///< D30F5 PSF base address (SCC: SDIO)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_EMMC_REG_BASE 0x0500 ///< D30F4 PSF base address (SCC: eMMC)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_OTG_REG_BASE 0x0600 ///< D20F1 PSF base address (USB device controller: OTG)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_XHCI_REG_BASE 0x0700 ///< D20F0 PSF base address (XHCI)
+// PSF2 PCH-H Specific Base Address
+#define R_PCH_H_PCR_PSF2_T0_SHDW_OTG_REG_BASE 0x0200 ///< D20F1 PSF base address (USB device controller: OTG)
+#define R_PCH_H_PCR_PSF2_T0_SHDW_XHCI_REG_BASE 0x0300 ///< D20F0 PSF base address (XHCI)
+
+//
+// PSF3 PCRs (PID:PSF3)
+//
+#define R_PCH_PCR_PSF3_T0_SHDW_P2SB_REG_BASE 0x0100 ///< D31F1 PSF base address (P2SB) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE 0x0200 ///< D20F4 PSF base address (TraceHub ACPI) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE 0x0300 ///< D31F7 PSF base address (TraceHub PCI) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_LPC_REG_BASE 0x0400 ///< D31F0 PSF base address (LPC) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE 0x0500 ///< D31F4 PSF base address (SMBUS) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_PMC_REG_BASE 0x0700 ///< D31F2 PSF base address (PMC) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE 0x0800 ///< D19F0 PSF base address (ISH) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_AUD_REG_BASE 0x1900 ///< D31F3 PSF base address (HDA, ADSP) // LP&H
+// PSF3 PCH-LP Specific Base Address
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C4_REG_BASE 0x0900 ///< D25F2 PSF base address (SerialIo: I2C4)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_SPI1_REG_BASE 0x0A00 ///< D30F3 PSF base address (SerialIo: SPI1)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_SPI0_REG_BASE 0x0B00 ///< D30F2 PSF base address (SerialIo: SPI0)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_UART1_REG_BASE 0x0C00 ///< D30F1 PSF base address (SerialIo: UART1)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_UART0_REG_BASE 0x0D00 ///< D30F0 PSF base address (SerialIo: UART0)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C5_REG_BASE 0x0E00 ///< D25F1 PSF base address (SerialIo: I2C5)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_UART2_REG_BASE 0x0F00 ///< D25F0 PSF base address (SerialIo: UART2)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C3_REG_BASE 0x1000 ///< D21F3 PSF base address (SerialIo: I2C3)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C2_REG_BASE 0x1100 ///< D21F2 PSF base address (SerialIo: I2C2)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C1_REG_BASE 0x1200 ///< D21F1 PSF base address (SerialIo: I2C1)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C0_REG_BASE 0x1300 ///< D21F0 PSF base address (SerialIo: I2C0)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_SPI_SPI_REG_BASE 0x1600 ///< D31F5 PSF base address (SPI SPI)
+// PSF3 PCH-H Specific Base Address
+#define R_PCH_H_PCR_PSF3_T0_SHDW_SPI1_REG_BASE 0x0900 ///< D30F3 PSF base address (SerialIo: SPI1)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_SPI0_REG_BASE 0x0A00 ///< D30F2 PSF base address (SerialIo: SPI0)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_UART1_REG_BASE 0x0B00 ///< D30F1 PSF base address (SerialIo: UART1)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_UART0_REG_BASE 0x0C00 ///< D30F0 PSF base address (SerialIo: UART0)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_UART2_REG_BASE 0x0D00 ///< D25F0 PSF base address (SerialIo: UART2)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C3_REG_BASE 0x0E00 ///< D21F3 PSF base address (SerialIo: I2C3)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C2_REG_BASE 0x0F00 ///< D21F2 PSF base address (SerialIo: I2C2)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C1_REG_BASE 0x1000 ///< D21F1 PSF base address (SerialIo: I2C1)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C0_REG_BASE 0x1100 ///< D21F0 PSF base address (SerialIo: I2C0)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_SPI_SPI_REG_BASE 0x1400 ///< D31F5 PSF base address (SPI SPI)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_GBE_REG_BASE 0x1700 ///< D31F6 PSF base address (GBE)
+
+#define R_PCH_PCR_PSF3_PSF_MC_CONTROL_MCAST0_EOI 0x404C ///< Multicast Control Register // LP&H
+#define R_PCH_PCR_PSF3_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x4054 ///< Destination ID // LP&H
+
+#define R_PCH_H_PCR_PSF3_PSF_PORT_CONFIG_PG1_PORT1 0x4020 ///< PSF Port Configuration Register
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h
new file mode 100644
index 0000000000..b312f7100e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h
@@ -0,0 +1,72 @@
+/** @file
+ Register definition for PSTH component
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_PSTH_H_
+#define _PCH_REGS_PSTH_H_
+
+//
+// Private chipset regsiter (Memory space) offset definition
+// The PCR register defines is used for PCR MMIO programming and PCH SBI programming as well.
+//
+
+//
+// PSTH and IO Trap PCRs (PID:PSTH)
+//
+#define R_PCH_PCR_PSTH_PSTHCTL 0x1D00 ///< PSTH control register
+#define B_PCH_PCR_PSTH_PSTHIOSFPTCGE BIT2 ///< PSTH IOSF primary trunk clock gating enable
+#define B_PCH_PCR_PSTH_PSTHIOSFSTCGE BIT1 ///< PSTH IOSF sideband trunk clock gating enable
+#define B_PCH_PCR_PSTH_PSTHDCGE BIT0 ///< PSTH dynamic clock gating enable
+#define R_PCH_PCR_PSTH_TRPST 0x1E00 ///< Trap status regsiter
+#define B_PCH_PCR_PSTH_TRPST_CTSS 0x0000000F ///< Cycle Trap SMI# Status mask
+#define R_PCH_PCR_PSTH_TRPC 0x1E10 ///< Trapped cycle
+#define B_PCH_PCR_PSTH_TRPC_RW BIT24 ///< Read/Write#: 1=Read, 0=Write
+#define B_PCH_PCR_PSTH_TRPC_AHBE 0x00000000000F0000 ///< Active high byte enables
+#define B_PCH_PCR_PSTH_TRPC_IOA 0x000000000000FFFC ///< Trap cycle I/O address
+#define R_PCH_PCR_PSTH_TRPD 0x1E18 ///< Trapped write data
+#define B_PCH_PCR_PSTH_TRPD_IOD 0x00000000FFFFFFFF ///< Trap cycle I/O data
+#define R_PCH_PCR_PSTH_TRPREG0 0x1E80 ///< IO Tarp 0 register
+#define R_PCH_PCR_PSTH_TRPREG1 0x1E88 ///< IO Tarp 1 register
+#define R_PCH_PCR_PSTH_TRPREG2 0x1E90 ///< IO Tarp 2 register
+#define R_PCH_PCR_PSTH_TRPREG3 0x1E98 ///< IO Tarp 3 register
+#define B_PCH_PCR_PSTH_TRPREG_RWM BIT17 ///< 49 - 32 for 32 bit access, Read/Write mask
+#define B_PCH_PCR_PSTH_TRPREG_RWIO BIT16 ///< 48 - 32 for 32 bit access, Read/Write#, 1=Read, 0=Write
+#define N_PCH_PCR_PSTH_TRPREG_RWIO 16 ///< 48 - 32 for 32 bit access, 16bit shift for Read/Write field
+#define N_PCH_PCR_PSTH_TRPREG_BEM (36 - 32)
+#define B_PCH_PCR_PSTH_TRPREG_BEM 0x000000F000000000 ///< Byte enable mask
+#define B_PCH_PCR_PSTH_TRPREG_BE 0x0000000F00000000 ///< Byte enable
+#define B_PCH_PCR_PSTH_TRPREG_AM 0x0000000000FC0000 ///< IO Address mask
+#define B_PCH_PCR_PSTH_TRPREG_AD 0x000000000000FFFC ///< IO Address
+#define B_PCH_PCR_PSTH_TRPREG_TSE BIT0 ///< Trap and SMI# Enable
+
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h
new file mode 100644
index 0000000000..88d066ea28
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h
@@ -0,0 +1,720 @@
+/** @file
+ Register names for PCH SATA controllers
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_SATA_H_
+#define _PCH_REGS_SATA_H_
+
+//
+// SATA Controller Registers (D23:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SATA 23
+#define PCI_FUNCTION_NUMBER_PCH_SATA 0
+#define V_PCH_SATA_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+
+//
+// SKL PCH-LP SATA Device ID's
+//
+#define V_PCH_LP_SATA_DEVICE_ID_M_AHCI 0x9D03 ///< SATA Controller (AHCI) - Mobile
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID 0x9D05 ///< SATA Controller (RAID 0/1/5/10) - NOT premium - Mobile
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID_ALTDIS 0x282A ///< SATA Controller (RAID 0/1/5/10) - NOT premium - Mobile - Alternate ID
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID_PREM 0x9D07 ///< SATA Controller (RAID 0/1/5/10) - premium - Mobile
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID_RRT 0x9D0F ///< SATA Controller (RAID 1/RRT Only) - Mobile
+
+//
+// PCH-H SATA Device ID's
+//
+#define V_PCH_H_SATA_DEVICE_ID_D_RAID_ALTDIS 0x2822 ///< SATA Controller (RAID 0/1/5/10) - premium - Alternate ID
+#define V_PCH_H_SATA_DEVICE_ID_D_RAID_RSTE 0x2826 ///< SATA Controller (RAID 0/1/5/10) - RSTe of Server SKU
+
+//
+// SKL PCH-H SATA Device ID's
+//
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI 0xA102 ///< SATA Controller (AHCI)
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI_A0 0xA103 ///< SATA Controller (AHCI) - SPTH A0
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID 0xA105 ///< SATA Controller (RAID 0/1/5/10) - NOT premium
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM 0xA107 ///< SATA Controller (RAID 0/1/5/10) - premium
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_RRT 0xA10F ///< SATA Controller (RAID 1/RRT Only)
+
+//
+// KBL PCH-H SATA Device ID's
+//
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_AHCI 0xA282 ///< SATA Controller (AHCI)
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID 0xA284 ///< SATA Controller (RAID 0/1/5/10) - NOT premium
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM 0xA286 ///< SATA Controller (RAID 0/1/5/10) - premium
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_OPTANE 0xA28E ///< SATA Controller (RAID 1/RRT Only)
+
+
+//
+// SATA Controller common Registers
+//
+#define V_PCH_SATA_SUB_CLASS_CODE_AHCI 0x06
+#define V_PCH_SATA_SUB_CLASS_CODE_RAID 0x04
+#define R_PCH_SATA_AHCI_BAR 0x24
+#define B_PCH_SATA_AHCI_BAR_BA 0xFFFFF800
+#define V_PCH_SATA_AHCI_BAR_LENGTH 0x800
+#define N_PCH_SATA_AHCI_BAR_ALIGNMENT 11
+#define V_PCH_SATA_AHCI_BAR_LENGTH_512K 0x80000
+#define N_PCH_SATA_AHCI_BAR_ALIGNMENT_512K 19
+#define B_PCH_SATA_AHCI_BAR_PF BIT3
+#define B_PCH_SATA_AHCI_BAR_TP (BIT2 | BIT1)
+#define B_PCH_SATA_AHCI_BAR_RTE BIT0
+#define R_PCH_SATA_PID 0x70
+#define B_PCH_SATA_PID_NEXT 0xFF00
+#define V_PCH_SATA_PID_NEXT_0 0xB000
+#define V_PCH_SATA_PID_NEXT_1 0xA800
+#define B_PCH_SATA_PID_CID 0x00FF
+#define R_PCH_SATA_PC 0x72
+#define S_PCH_SATA_PC 2
+#define B_PCH_SATA_PC_PME (BIT15 | BIT14 | BIT13 | BIT12 | BIT11)
+#define V_PCH_SATA_PC_PME_0 0x0000
+#define V_PCH_SATA_PC_PME_1 0x4000
+#define B_PCH_SATA_PC_D2_SUP BIT10
+#define B_PCH_SATA_PC_D1_SUP BIT9
+#define B_PCH_SATA_PC_AUX_CUR (BIT8 | BIT7 | BIT6)
+#define B_PCH_SATA_PC_DSI BIT5
+#define B_PCH_SATA_PC_PME_CLK BIT3
+#define B_PCH_SATA_PC_VER (BIT2 | BIT1 | BIT0)
+#define R_PCH_SATA_PMCS 0x74
+#define B_PCH_SATA_PMCS_PMES BIT15
+#define B_PCH_SATA_PMCS_PMEE BIT8
+#define B_PCH_SATA_PMCS_NSFRST BIT3
+#define V_PCH_SATA_PMCS_NSFRST_1 0x01
+#define V_PCH_SATA_PMCS_NSFRST_0 0x00
+#define B_PCH_SATA_PMCS_PS (BIT1 | BIT0)
+#define V_PCH_SATA_PMCS_PS_3 0x03
+#define V_PCH_SATA_PMCS_PS_0 0x00
+#define R_PCH_SATA_MID 0x80
+#define B_PCH_SATA_MID_NEXT 0xFF00
+#define B_PCH_SATA_MID_CID 0x00FF
+#define R_PCH_SATA_MC 0x82
+#define B_PCH_SATA_MC_C64 BIT7
+#define B_PCH_SATA_MC_MME (BIT6 | BIT5 | BIT4)
+#define V_PCH_SATA_MC_MME_4 0x04
+#define V_PCH_SATA_MC_MME_2 0x02
+#define V_PCH_SATA_MC_MME_1 0x01
+#define V_PCH_SATA_MC_MME_0 0x00
+#define B_PCH_SATA_MC_MMC (BIT3 | BIT2 | BIT1)
+#define V_PCH_SATA_MC_MMC_4 0x04
+#define V_PCH_SATA_MC_MMC_0 0x00
+#define B_PCH_SATA_MC_MSIE BIT0
+#define V_PCH_SATA_MC_MSIE_1 0x01
+#define V_PCH_SATA_MC_MSIE_0 0x00
+#define R_PCH_SATA_MA 0x84
+#define B_PCH_SATA_MA 0xFFFFFFFC
+#define R_PCH_SATA_MD 0x88
+#define B_PCH_SATA_MD_MSIMD 0xFFFF
+
+//
+// Sata Register for PCH-LP
+//
+#define R_PCH_LP_SATA_MAP 0x90
+#define B_PCH_LP_SATA_MAP_SPD (BIT10 | BIT9 | BIT8)
+#define N_PCH_LP_SATA_MAP_SPD 8
+#define B_PCH_LP_SATA_MAP_SPD2 BIT10
+#define B_PCH_LP_SATA_MAP_SPD1 BIT9
+#define B_PCH_LP_SATA_MAP_SPD0 BIT8
+#define B_PCH_LP_SATA_MAP_SMS_MASK BIT6
+#define N_PCH_LP_SATA_MAP_SMS_MASK 6
+#define V_PCH_LP_SATA_MAP_SMS_AHCI 0x0
+#define V_PCH_LP_SATA_MAP_SMS_RAID 0x1
+#define R_PCH_LP_SATA_PCS 0x92
+#define B_PCH_LP_SATA_PCS_OOB_RETRY BIT15
+#define B_PCH_LP_SATA_PCS_P2P BIT10
+#define B_PCH_LP_SATA_PCS_P1P BIT9
+#define B_PCH_LP_SATA_PCS_P0P BIT8
+#define B_PCH_LP_SATA_PCS_PXE_MASK (BIT2 | BIT1 | BIT0)
+#define B_PCH_LP_SATA_PCS_P2E BIT2
+#define B_PCH_LP_SATA_PCS_P1E BIT1
+#define B_PCH_LP_SATA_PCS_P0E BIT0
+#define R_PCH_LP_SATA_SCLKGC 0x94
+#define B_PCH_LP_SATA_SCLKGC_PCD (BIT26 | BIT25 | BIT24)
+#define B_PCH_LP_SATA_SCLKGC_PORT2_PCD BIT26
+#define B_PCH_LP_SATA_SCLKGC_PORT1_PCD BIT25
+#define B_PCH_LP_SATA_SCLKGC_PORT0_PCD BIT24
+#define R_PCH_LP_SATA_98 0x98
+
+//
+// Sata Register for PCH-H
+//
+#define R_PCH_H_SATA_MAP 0x90
+#define B_PCH_H_SATA_MAP_SPD 0xFF0000
+#define N_PCH_H_SATA_MAP_SPD 16
+#define B_PCH_H_SATA_MAP_SPD7 BIT23
+#define B_PCH_H_SATA_MAP_SPD6 BIT22
+#define B_PCH_H_SATA_MAP_SPD5 BIT21
+#define B_PCH_H_SATA_MAP_SPD4 BIT20
+#define B_PCH_H_SATA_MAP_SPD3 BIT19
+#define B_PCH_H_SATA_MAP_SPD2 BIT18
+#define B_PCH_H_SATA_MAP_SPD1 BIT17
+#define B_PCH_H_SATA_MAP_SPD0 BIT16
+#define B_PCH_H_SATA_MAP_PCD 0xFF
+#define B_PCH_H_SATA_MAP_PORT7_PCD BIT7
+#define B_PCH_H_SATA_MAP_PORT6_PCD BIT6
+#define B_PCH_H_SATA_MAP_PORT5_PCD BIT5
+#define B_PCH_H_SATA_MAP_PORT4_PCD BIT4
+#define B_PCH_H_SATA_MAP_PORT3_PCD BIT3
+#define B_PCH_H_SATA_MAP_PORT2_PCD BIT2
+#define B_PCH_H_SATA_MAP_PORT1_PCD BIT1
+#define B_PCH_H_SATA_MAP_PORT0_PCD BIT0
+#define R_PCH_H_SATA_PCS 0x94
+#define B_PCH_H_SATA_PCS_P7P BIT23
+#define B_PCH_H_SATA_PCS_P6P BIT22
+#define B_PCH_H_SATA_PCS_P5P BIT21
+#define B_PCH_H_SATA_PCS_P4P BIT20
+#define B_PCH_H_SATA_PCS_P3P BIT19
+#define B_PCH_H_SATA_PCS_P2P BIT18
+#define B_PCH_H_SATA_PCS_P1P BIT17
+#define B_PCH_H_SATA_PCS_P0P BIT16
+#define B_PCH_H_SATA_PCS_PXE_MASK 0xFF
+#define B_PCH_H_SATA_PCS_P7E BIT7
+#define B_PCH_H_SATA_PCS_P6E BIT6
+#define B_PCH_H_SATA_PCS_P5E BIT5
+#define B_PCH_H_SATA_PCS_P4E BIT4
+#define B_PCH_H_SATA_PCS_P3E BIT3
+#define B_PCH_H_SATA_PCS_P2E BIT2
+#define B_PCH_H_SATA_PCS_P1E BIT1
+#define B_PCH_H_SATA_PCS_P0E BIT0
+
+#define R_PCH_SATA_SATAGC 0x9C
+#define B_PCH_H_SATA_SATAGC_SMS_MASK BIT16
+#define N_PCH_H_SATA_SATAGC_SMS_MASK 16
+#define V_PCH_H_SATA_SATAGC_SMS_AHCI 0x0
+#define V_PCH_H_SATA_SATAGC_SMS_RAID 0x1
+#define B_PCH_SATA_SATAGC_AIE BIT7
+#define B_PCH_SATA_SATAGC_AIES BIT6
+#define B_PCH_SATA_SATAGC_MSS (BIT4 | BIT3)
+#define V_PCH_SATA_SATAGC_MSS_8K 0x2
+#define N_PCH_SATA_SATAGC_MSS 3
+#define B_PCH_SATA_SATAGC_ASSEL (BIT2 | BIT1 | BIT0)
+
+#define V_PCH_SATA_SATAGC_ASSEL_2K 0x0
+#define V_PCH_SATA_SATAGC_ASSEL_16K 0x1
+#define V_PCH_SATA_SATAGC_ASSEL_32K 0x2
+#define V_PCH_SATA_SATAGC_ASSEL_64K 0x3
+#define V_PCH_SATA_SATAGC_ASSEL_128K 0x4
+#define V_PCH_SATA_SATAGC_ASSEL_256K 0x5
+#define V_PCH_SATA_SATAGC_ASSEL_512K 0x6
+
+#define R_PCH_SATA_SIRI 0xA0
+#define R_PCH_SATA_STRD 0xA4
+#define R_PCH_SATA_SIR_0C 0x0C
+#define R_PCH_SATA_SIR_50 0x50
+#define R_PCH_SATA_SIR_54 0x54
+#define R_PCH_SATA_SIR_58 0x58
+#define R_PCH_SATA_SIR_5C 0x5C
+#define R_PCH_SATA_SIR_60 0x60
+#define R_PCH_SATA_SIR_64 0x64
+#define R_PCH_SATA_SIR_68 0x68
+#define R_PCH_SATA_SIR_6C 0x6C
+#define R_PCH_SATA_SIR_70 0x70
+#define R_PCH_SATA_SIR_80 0x80
+#define R_PCH_SATA_SIR_84 0x84
+#define R_PCH_SATA_SIR_8C 0x8C
+#define R_PCH_SATA_SIR_90 0x90
+#define R_PCH_SATA_SIR_98 0x98
+#define R_PCH_SATA_SIR_9C 0x9C
+#define R_PCH_SATA_SIR_A0 0xA0
+#define R_PCH_SATA_SIR_A4 0xA4
+#define R_PCH_SATA_SIR_A8 0xA8
+#define R_PCH_SATA_SIR_C8 0xC8
+#define R_PCH_SATA_SIR_CC 0xCC
+#define R_PCH_SATA_SIR_D0 0xD0
+#define R_PCH_SATA_SIR_D4 0xD4
+#define B_PCH_SATA_STRD_DTA 0xFFFFFFFF
+#define R_PCH_SATA_CR0 0xA8
+#define B_PCH_SATA_CR0_MAJREV 0x00F00000
+#define B_PCH_SATA_CR0_MINREV 0x000F0000
+#define B_PCH_SATA_CR0_NEXT 0x0000FF00
+#define B_PCH_SATA_CR0_CAP 0x000000FF
+#define R_PCH_SATA_CR1 0xAC
+#define B_PCH_SATA_CR1_BAROFST 0xFFF0
+#define B_PCH_SATA_CR1_BARLOC 0x000F
+#define R_PCH_SATA_FLR_CID 0xB0
+#define B_PCH_SATA_FLR_CID_NEXT 0xFF00
+#define B_PCH_SATA_FLR_CID 0x00FF
+#define V_PCH_SATA_FLR_CID_1 0x0009
+#define V_PCH_SATA_FLR_CID_0 0x0013
+#define R_PCH_SATA_FLR_CLV 0xB2
+#define B_PCH_SATA_FLR_CLV_FLRC_FLRCSSEL_0 BIT9
+#define B_PCH_SATA_FLR_CLV_TXPC_FLRCSSEL_0 BIT8
+#define B_PCH_SATA_FLR_CLV_VSCID_FLRCSSEL_0 0x00FF
+#define B_PCH_SATA_FLR_CLV_VSCID_FLRCSSEL_1 0x00FF
+#define V_PCH_SATA_FLR_CLV_VSCID_FLRCSSEL 0x0006
+#define R_PCH_SATA_FLRC 0xB4
+#define B_PCH_SATA_FLRC_TXP BIT8
+#define B_PCH_SATA_FLRC_INITFLR BIT0
+#define R_PCH_SATA_SP 0xC0
+#define B_PCH_SATA_SP 0xFFFFFFFF
+#define R_PCH_SATA_MXID 0xD0
+#define N_PCH_SATA_MXID_NEXT 8
+
+#define R_PCH_SATA_BFCS 0xE0
+#define B_PCH_SATA_BFCS_P7BFI BIT17
+#define B_PCH_SATA_BFCS_P6BFI BIT16
+#define B_PCH_SATA_BFCS_P5BFI BIT15
+#define B_PCH_SATA_BFCS_P4BFI BIT14
+#define B_PCH_SATA_BFCS_P3BFI BIT13
+#define B_PCH_SATA_BFCS_P2BFI BIT12
+#define B_PCH_SATA_BFCS_P2BFS BIT11
+#define B_PCH_SATA_BFCS_P2BFF BIT10
+#define B_PCH_SATA_BFCS_P1BFI BIT9
+#define B_PCH_SATA_BFCS_P0BFI BIT8
+#define B_PCH_SATA_BFCS_BIST_FIS_T BIT7
+#define B_PCH_SATA_BFCS_BIST_FIS_A BIT6
+#define B_PCH_SATA_BFCS_BIST_FIS_S BIT5
+#define B_PCH_SATA_BFCS_BIST_FIS_L BIT4
+#define B_PCH_SATA_BFCS_BIST_FIS_F BIT3
+#define B_PCH_SATA_BFCS_BIST_FIS_P BIT2
+#define R_PCH_SATA_BFTD1 0xE4
+#define B_PCH_SATA_BFTD1 0xFFFFFFFF
+#define R_PCH_SATA_BFTD2 0xE8
+#define B_PCH_SATA_BFTD2 0xFFFFFFFF
+
+#define R_PCH_SATA_VS_CAP 0xA4
+#define B_PCH_SATA_VS_CAP_NRMBE BIT0 ///< NVM Remap Memory BAR Enable
+#define B_PCH_SATA_VS_CAP_MSL 0x1FFE ///< Memory Space Limit
+#define N_PCH_SATA_VS_CAP_MSL 1
+#define V_PCH_SATA_VS_CAP_MSL 0x1EF ///< Memory Space Limit Field Value
+#define B_PCH_SATA_VS_CAP_NRMO 0xFFF0000 ///< NVM Remapped Memory Offset
+#define N_PCH_SATA_VS_CAP_NRMO 16
+#define V_PCH_SATA_VS_CAP_NRMO 0x10 ///< NVM Remapped Memory Offset Field Value
+
+//
+// RST PCIe Storage Remapping Registers
+//
+#define R_PCH_RST_PCIE_STORAGE_RCR 0x800 ///< Remap Capability Register
+#define B_PCH_RST_PCIE_STORAGE_RCR_NRS (BIT2|BIT1|BIT0) ///< Number of Remapping Supported
+#define B_PCH_RST_PCIE_STORAGE_RCR_NRS_CR1 BIT0 ///< Number of Remapping Supported (RST PCIe Storage Cycle Router #1)
+#define R_PCH_RST_PCIE_STORAGE_SPR 0x80C ///< Scratch Pad Register
+#define R_PCH_RST_PCIE_STORAGE_CR1_DCC 0x880 ///< CR#1 Device Class Code
+#define N_PCH_RST_PCIE_STORAGE_CR1_DCC_SCC 8
+#define N_PCH_RST_PCIE_STORAGE_CR1_DCC_BCC 16
+#define B_PCH_RST_PCIE_STORAGE_CR1_DCC_DT BIT31 ///< Device Type
+#define V_PCH_RST_PCIE_STORAGE_REMAP_CONFIG_CR 0x80 ///< Remapped Configuration for RST PCIe Storage Cycle Router #n
+#define V_PCH_RST_PCIE_STORAGE_REMAP_RP_OFFSET 0x100 ///< Remapped Root Port Offset Value
+#define R_PCH_RST_PCIE_STORAGE_CCFG 0x1D0 ///< Port Configuration Register
+
+//
+// AHCI BAR Area related Registers
+//
+#define R_PCH_SATA_AHCI_CAP 0x0
+#define B_PCH_SATA_AHCI_CAP_S64A BIT31
+#define B_PCH_SATA_AHCI_CAP_SCQA BIT30
+#define B_PCH_SATA_AHCI_CAP_SSNTF BIT29
+#define B_PCH_SATA_AHCI_CAP_SIS BIT28 ///< Supports Interlock Switch
+#define B_PCH_SATA_AHCI_CAP_SSS BIT27 ///< Supports Stagger Spin-up
+#define B_PCH_SATA_AHCI_CAP_SALP BIT26
+#define B_PCH_SATA_AHCI_CAP_SAL BIT25
+#define B_PCH_SATA_AHCI_CAP_SCLO BIT24 ///< Supports Command List Override
+#define B_PCH_SATA_AHCI_CAP_ISS_MASK (BIT23 | BIT22 | BIT21 | BIT20)
+#define N_PCH_SATA_AHCI_CAP_ISS 20 ///< Interface Speed Support
+#define V_PCH_SATA_AHCI_CAP_ISS_1_5_G 0x01
+#define V_PCH_SATA_AHCI_CAP_ISS_3_0_G 0x02
+#define V_PCH_SATA_AHCI_CAP_ISS_6_0_G 0x03
+#define B_PCH_SATA_AHCI_CAP_SNZO BIT19
+#define B_PCH_SATA_AHCI_CAP_SAM BIT18
+#define B_PCH_SATA_AHCI_CAP_PMS BIT17 ///< Supports Port Multiplier
+#define B_PCH_SATA_AHCI_CAP_PMD BIT15 ///< PIO Multiple DRQ Block
+#define B_PCH_SATA_AHCI_CAP_SSC BIT14
+#define B_PCH_SATA_AHCI_CAP_PSC BIT13
+#define B_PCH_SATA_AHCI_CAP_NCS 0x1F00
+#define B_PCH_SATA_AHCI_CAP_CCCS BIT7
+#define B_PCH_SATA_AHCI_CAP_EMS BIT6
+#define B_PCH_SATA_AHCI_CAP_SXS BIT5 ///< External SATA is supported
+#define B_PCH_SATA_AHCI_CAP_NPS 0x001F
+
+#define R_PCH_SATA_AHCI_GHC 0x04
+#define B_PCH_SATA_AHCI_GHC_AE BIT31
+#define B_PCH_SATA_AHCI_GHC_MRSM BIT2
+#define B_PCH_SATA_AHCI_GHC_IE BIT1
+#define B_PCH_SATA_AHCI_GHC_HR BIT0
+
+#define R_PCH_SATA_AHCI_IS 0x08
+#define B_PCH_SATA_AHCI_IS_PORT7 BIT7
+#define B_PCH_SATA_AHCI_IS_PORT6 BIT6
+#define B_PCH_SATA_AHCI_IS_PORT5 BIT5
+#define B_PCH_SATA_AHCI_IS_PORT4 BIT4
+#define B_PCH_SATA_AHCI_IS_PORT3 BIT3
+#define B_PCH_SATA_AHCI_IS_PORT2 BIT2
+#define B_PCH_SATA_AHCI_IS_PORT1 BIT1
+#define B_PCH_SATA_AHCI_IS_PORT0 BIT0
+#define R_PCH_SATA_AHCI_PI 0x0C
+#define B_PCH_H_SATA_PORT_MASK 0xFF
+#define B_PCH_LP_SATA_PORT_MASK 0x03
+#define B_PCH_SATA_PORT7_IMPLEMENTED BIT7
+#define B_PCH_SATA_PORT6_IMPLEMENTED BIT6
+#define B_PCH_SATA_PORT5_IMPLEMENTED BIT5
+#define B_PCH_SATA_PORT4_IMPLEMENTED BIT4
+#define B_PCH_SATA_PORT3_IMPLEMENTED BIT3
+#define B_PCH_SATA_PORT2_IMPLEMENTED BIT2
+#define B_PCH_SATA_PORT1_IMPLEMENTED BIT1
+#define B_PCH_SATA_PORT0_IMPLEMENTED BIT0
+#define R_PCH_SATA_AHCI_VS 0x10
+#define B_PCH_SATA_AHCI_VS_MJR 0xFFFF0000
+#define B_PCH_SATA_AHCI_VS_MNR 0x0000FFFF
+#define R_PCH_SATA_AHCI_EM_LOC 0x1C
+#define B_PCH_SATA_AHCI_EM_LOC_OFST 0xFFFF0000
+#define B_PCH_SATA_AHCI_EM_LOC_SZ 0x0000FFFF
+#define R_PCH_SATA_AHCI_EM_CTRL 0x20
+#define B_PCH_SATA_AHCI_EM_CTRL_ATTR_ALHD BIT26
+#define B_PCH_SATA_AHCI_EM_CTRL_ATTR_XMT BIT25
+#define B_PCH_SATA_AHCI_EM_CTRL_ATTR_SMB BIT24
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_SGPIO BIT19
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_SES2 BIT18
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_SAFTE BIT17
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_LED BIT16
+#define B_PCH_SATA_AHCI_EM_CTRL_RST BIT9
+#define B_PCH_SATA_AHCI_EM_CTRL_CTL_TM BIT8
+#define B_PCH_SATA_AHCI_EM_CTRL_STS_MR BIT0
+#define R_PCH_SATA_AHCI_CAP2 0x24
+#define B_PCH_SATA_AHCI_CAP2_DESO BIT5
+#define B_PCH_SATA_AHCI_CAP2_SADM BIT4
+#define B_PCH_SATA_AHCI_CAP2_SDS BIT3
+#define B_PCH_SATA_AHCI_CAP2_APST BIT2 ///< Automatic Partial to Slumber Transitions
+#define R_PCH_SATA_AHCI_VSP 0xA0
+#define B_PCH_SATA_AHCI_VSP_SLPD BIT0
+#define R_PCH_SATA_AHCI_RSTF 0xC8 ///< RST Feature Capabilities
+#define B_PCH_SATA_AHCI_RSTF_OMA BIT13
+#define B_PCH_SATA_AHCI_RSTF_LEGACY BIT12
+#define B_PCH_SATA_AHCI_RSTF_OUD (BIT11 | BIT10)
+#define N_PCH_SATA_AHCI_RSTF_OUD 10
+#define B_PCH_SATA_AHCI_RSTF_SEREQ BIT9
+#define B_PCH_SATA_AHCI_RSTF_IROES BIT8
+#define B_PCH_SATA_AHCI_RSTF_LEDL BIT7
+#define B_PCH_SATA_AHCI_RSTF_HDDLK BIT6
+#define B_PCH_SATA_AHCI_RSTF_IRSTOROM BIT5
+#define B_PCH_SATA_AHCI_RSTF_RSTE BIT4
+#define B_PCH_SATA_AHCI_RSTF_R5E BIT3
+#define B_PCH_SATA_AHCI_RSTF_R10E BIT2
+#define B_PCH_SATA_AHCI_RSTF_R1E BIT1
+#define B_PCH_SATA_AHCI_RSTF_R0E BIT0
+#define B_PCH_SATA_AHCI_RSTF_LOWBYTES 0x1FF
+#define R_PCH_SATA_AHCI_P0CLB 0x100
+#define R_PCH_SATA_AHCI_P1CLB 0x180
+#define R_PCH_SATA_AHCI_P2CLB 0x200
+#define R_PCH_SATA_AHCI_P3CLB 0x280
+#define R_PCH_SATA_AHCI_P4CLB 0x300
+#define R_PCH_SATA_AHCI_P5CLB 0x380
+#define R_PCH_SATA_AHCI_P6CLB 0x400
+#define R_PCH_SATA_AHCI_P7CLB 0x480
+#define B_PCH_SATA_AHCI_PXCLB 0xFFFFFC00
+#define R_PCH_SATA_AHCI_P0CLBU 0x104
+#define R_PCH_SATA_AHCI_P1CLBU 0x184
+#define R_PCH_SATA_AHCI_P2CLBU 0x204
+#define R_PCH_SATA_AHCI_P3CLBU 0x284
+#define R_PCH_SATA_AHCI_P4CLBU 0x304
+#define R_PCH_SATA_AHCI_P5CLBU 0x384
+#define R_PCH_SATA_AHCI_P6CLBU 0x404
+#define R_PCH_SATA_AHCI_P7CLBU 0x484
+#define B_PCH_SATA_AHCI_PXCLBU 0xFFFFFFFF
+#define R_PCH_SATA_AHCI_P0FB 0x108
+#define R_PCH_SATA_AHCI_P1FB 0x188
+#define R_PCH_SATA_AHCI_P2FB 0x208
+#define R_PCH_SATA_AHCI_P3FB 0x288
+#define R_PCH_SATA_AHCI_P4FB 0x308
+#define R_PCH_SATA_AHCI_P5FB 0x388
+#define R_PCH_SATA_AHCI_P6FB 0x408
+#define R_PCH_SATA_AHCI_P7FB 0x488
+#define B_PCH_SATA_AHCI_PXFB 0xFFFFFF00
+#define R_PCH_SATA_AHCI_P0FBU 0x10C
+#define R_PCH_SATA_AHCI_P1FBU 0x18C
+#define R_PCH_SATA_AHCI_P2FBU 0x20C
+#define R_PCH_SATA_AHCI_P3FBU 0x28C
+#define R_PCH_SATA_AHCI_P4FBU 0x30C
+#define R_PCH_SATA_AHCI_P5FBU 0x38C
+#define R_PCH_SATA_AHCI_P6FBU 0x40C
+#define R_PCH_SATA_AHCI_P7FBU 0x48C
+#define B_PCH_SATA_AHCI_PXFBU 0xFFFFFFFF
+#define R_PCH_SATA_AHCI_P0IS 0x110
+#define R_PCH_SATA_AHCI_P1IS 0x190
+#define R_PCH_SATA_AHCI_P2IS 0x210
+#define R_PCH_SATA_AHCI_P3IS 0x290
+#define R_PCH_SATA_AHCI_P4IS 0x310
+#define R_PCH_SATA_AHCI_P5IS 0x390
+#define R_PCH_SATA_AHCI_P6IS 0x410
+#define R_PCH_SATA_AHCI_P7IS 0x490
+#define B_PCH_SATA_AHCI_PXIS_CPDS BIT31
+#define B_PCH_SATA_AHCI_PXIS_TFES BIT30
+#define B_PCH_SATA_AHCI_PXIS_HBFS BIT29
+#define B_PCH_SATA_AHCI_PXIS_HBDS BIT28
+#define B_PCH_SATA_AHCI_PXIS_IFS BIT27
+#define B_PCH_SATA_AHCI_PXIS_INFS BIT26
+#define B_PCH_SATA_AHCI_PXIS_OFS BIT24
+#define B_PCH_SATA_AHCI_PXIS_IPMS BIT23
+#define B_PCH_SATA_AHCI_PXIS_PRCS BIT22
+#define B_PCH_SATA_AHCI_PXIS_DIS BIT7
+#define B_PCH_SATA_AHCI_PXIS_PCS BIT6
+#define B_PCH_SATA_AHCI_PXIS_DPS BIT5
+#define B_PCH_SATA_AHCI_PXIS_UFS BIT4
+#define B_PCH_SATA_AHCI_PXIS_SDBS BIT3
+#define B_PCH_SATA_AHCI_PXIS_DSS BIT2
+#define B_PCH_SATA_AHCI_PXIS_PSS BIT1
+#define B_PCH_SATA_AHCI_PXIS_DHRS BIT0
+#define R_PCH_SATA_AHCI_P0IE 0x114
+#define R_PCH_SATA_AHCI_P1IE 0x194
+#define R_PCH_SATA_AHCI_P2IE 0x214
+#define R_PCH_SATA_AHCI_P3IE 0x294
+#define R_PCH_SATA_AHCI_P4IE 0x314
+#define R_PCH_SATA_AHCI_P5IE 0x394
+#define R_PCH_SATA_AHCI_P6IE 0x414
+#define R_PCH_SATA_AHCI_P7IE 0x494
+#define B_PCH_SATA_AHCI_PXIE_CPDE BIT31
+#define B_PCH_SATA_AHCI_PXIE_TFEE BIT30
+#define B_PCH_SATA_AHCI_PXIE_HBFE BIT29
+#define B_PCH_SATA_AHCI_PXIE_HBDE BIT28
+#define B_PCH_SATA_AHCI_PXIE_IFE BIT27
+#define B_PCH_SATA_AHCI_PXIE_INFE BIT26
+#define B_PCH_SATA_AHCI_PXIE_OFE BIT24
+#define B_PCH_SATA_AHCI_PXIE_IPME BIT23
+#define B_PCH_SATA_AHCI_PXIE_PRCE BIT22
+#define B_PCH_SATA_AHCI_PXIE_DIE BIT7
+#define B_PCH_SATA_AHCI_PXIE_PCE BIT6
+#define B_PCH_SATA_AHCI_PXIE_DPE BIT5
+#define B_PCH_SATA_AHCI_PXIE_UFIE BIT4
+#define B_PCH_SATA_AHCI_PXIE_SDBE BIT3
+#define B_PCH_SATA_AHCI_PXIE_DSE BIT2
+#define B_PCH_SATA_AHCI_PXIE_PSE BIT1
+#define B_PCH_SATA_AHCI_PXIE_DHRE BIT0
+#define R_PCH_SATA_AHCI_P0CMD 0x118
+#define R_PCH_SATA_AHCI_P1CMD 0x198
+#define R_PCH_SATA_AHCI_P2CMD 0x218
+#define R_PCH_SATA_AHCI_P3CMD 0x298
+#define R_PCH_SATA_AHCI_P4CMD 0x318
+#define R_PCH_SATA_AHCI_P5CMD 0x398
+#define R_PCH_SATA_AHCI_P6CMD 0x418
+#define R_PCH_SATA_AHCI_P7CMD 0x498
+#define B_PCH_SATA_AHCI_PxCMD_ICC (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_SATA_AHCI_PxCMD_MASK (BIT27 | BIT26 | BIT22 | BIT21 | BIT19 | BIT18)
+#define B_PCH_SATA_AHCI_PxCMD_ASP BIT27
+#define B_PCH_SATA_AHCI_PxCMD_ALPE BIT26
+#define B_PCH_SATA_AHCI_PxCMD_DLAE BIT25
+#define B_PCH_SATA_AHCI_PxCMD_ATAPI BIT24
+#define B_PCH_SATA_AHCI_PxCMD_APSTE BIT23
+#define B_PCH_SATA_AHCI_PxCMD_SUD BIT1
+#define R_PCH_SATA_AHCI_P0DEVSLP 0x144
+#define R_PCH_SATA_AHCI_P1DEVSLP 0x1C4
+#define R_PCH_SATA_AHCI_P2DEVSLP 0x244
+#define R_PCH_SATA_AHCI_P3DEVSLP 0x2C4
+#define R_PCH_SATA_AHCI_P4DEVSLP 0x344
+#define R_PCH_SATA_AHCI_P5DEVSLP 0x3C4
+#define R_PCH_SATA_AHCI_P6DEVSLP 0x444
+#define R_PCH_SATA_AHCI_P7DEVSLP 0x4C4
+#define B_PCH_SATA_AHCI_PxDEVSLP_DSP BIT1
+#define B_PCH_SATA_AHCI_PxDEVSLP_ADSE BIT0
+#define B_PCH_SATA_AHCI_PxDEVSLP_DITO_MASK 0x01FF8000
+#define V_PCH_SATA_AHCI_PxDEVSLP_DITO_625 0x01388000
+#define B_PCH_SATA_AHCI_PxDEVSLP_DM_MASK 0x1E000000
+#define V_PCH_SATA_AHCI_PxDEVSLP_DM_16 0x1E000000
+#define B_PCH_SATA_AHCI_PxCMD_ESP BIT21 ///< Used with an external SATA device
+#define B_PCH_SATA_AHCI_PxCMD_MPSP BIT19 ///< Mechanical Switch Attached to Port
+#define B_PCH_SATA_AHCI_PxCMD_HPCP BIT18 ///< Hotplug capable
+#define B_PCH_SATA_AHCI_PxCMD_CR BIT15
+#define B_PCH_SATA_AHCI_PxCMD_FR BIT14
+#define B_PCH_SATA_AHCI_PxCMD_ISS BIT13
+#define B_PCH_SATA_AHCI_PxCMD_CCS 0x00001F00
+#define B_PCH_SATA_AHCI_PxCMD_FRE BIT4
+#define B_PCH_SATA_AHCI_PxCMD_CLO BIT3
+#define B_PCH_SATA_AHCI_PxCMD_POD BIT2
+#define B_PCH_SATA_AHCI_PxCMD_SUD BIT1
+#define B_PCH_SATA_AHCI_PxCMD_ST BIT0
+#define R_PCH_SATA_AHCI_P0TFD 0x120
+#define R_PCH_SATA_AHCI_P1TFD 0x1A0
+#define R_PCH_SATA_AHCI_P2TFD 0x220
+#define R_PCH_SATA_AHCI_P3TFD 0x2A0
+#define R_PCH_SATA_AHCI_P4TFD 0x320
+#define R_PCH_SATA_AHCI_P5TFD 0x3A0
+#define R_PCH_SATA_AHCI_P6TFD 0x420
+#define B_PCH_SATA_AHCI_PXTFD_ERR 0x0000FF00
+#define B_PCH_SATA_AHCI_PXTFD_STS 0x000000FF
+#define R_PCH_SATA_AHCI_P0SIG 0x124
+#define R_PCH_SATA_AHCI_P1SIG 0x1A4
+#define R_PCH_SATA_AHCI_P2SIG 0x224
+#define R_PCH_SATA_AHCI_P3SIG 0x2A4
+#define R_PCH_SATA_AHCI_P4SIG 0x324
+#define R_PCH_SATA_AHCI_P5SIG 0x3A4
+#define R_PCH_SATA_AHCI_P6SIG 0x424
+#define B_PCH_SATA_AHCI_PXSIG_LBA_HR 0xFF000000
+#define B_PCH_SATA_AHCI_PXSIG_LBA_MR 0x00FF0000
+#define B_PCH_SATA_AHCI_PXSIG_LBA_LR 0x0000FF00
+#define B_PCH_SATA_AHCI_PXSIG_SCR 0x000000FF
+#define R_PCH_SATA_AHCI_P0SSTS 0x128
+#define R_PCH_SATA_AHCI_P1SSTS 0x1A8
+#define R_PCH_SATA_AHCI_P2SSTS 0x228
+#define R_PCH_SATA_AHCI_P3SSTS 0x2A8
+#define R_PCH_SATA_AHCI_P4SSTS 0x328
+#define R_PCH_SATA_AHCI_P5SSTS 0x3A8
+#define R_PCH_SATA_AHCI_P6SSTS 0x428
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_0 0x00000000
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_1 0x00000100
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_2 0x00000200
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_6 0x00000600
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_0 0x00000000
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_1 0x00000010
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_2 0x00000020
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_3 0x00000030
+#define B_PCH_SATA_AHCI_PXSSTS_DET_0 0x00000000
+#define B_PCH_SATA_AHCI_PXSSTS_DET_1 0x00000001
+#define B_PCH_SATA_AHCI_PXSSTS_DET_3 0x00000003
+#define B_PCH_SATA_AHCI_PXSSTS_DET_4 0x00000004
+#define R_PCH_SATA_AHCI_P0SCTL 0x12C
+#define R_PCH_SATA_AHCI_P1SCTL 0x1AC
+#define R_PCH_SATA_AHCI_P2SCTL 0x22C
+#define R_PCH_SATA_AHCI_P3SCTL 0x2AC
+#define R_PCH_SATA_AHCI_P4SCTL 0x32C
+#define R_PCH_SATA_AHCI_P5SCTL 0x3AC
+#define R_PCH_SATA_AHCI_P6SCTL 0x42C
+#define B_PCH_SATA_AHCI_PXSCTL_IPM 0x00000F00
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_0 0x00000000
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_1 0x00000100
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_2 0x00000200
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_3 0x00000300
+#define B_PCH_SATA_AHCI_PXSCTL_SPD 0x000000F0
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_0 0x00000000
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_1 0x00000010
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_2 0x00000020
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_3 0x00000030
+#define B_PCH_SATA_AHCI_PXSCTL_DET 0x0000000F
+#define V_PCH_SATA_AHCI_PXSCTL_DET_0 0x00000000
+#define V_PCH_SATA_AHCI_PXSCTL_DET_1 0x00000001
+#define V_PCH_SATA_AHCI_PXSCTL_DET_4 0x00000004
+#define R_PCH_SATA_AHCI_P0SERR 0x130
+#define R_PCH_SATA_AHCI_P1SERR 0x1B0
+#define R_PCH_SATA_AHCI_P2SERR 0x230
+#define R_PCH_SATA_AHCI_P3SERR 0x2B0
+#define R_PCH_SATA_AHCI_P4SERR 0x330
+#define R_PCH_SATA_AHCI_P5SERR 0x3B0
+#define R_PCH_SATA_AHCI_P6SERR 0x430
+#define B_PCH_SATA_AHCI_PXSERR_EXCHG BIT26
+#define B_PCH_SATA_AHCI_PXSERR_UN_FIS_TYPE BIT25
+#define B_PCH_SATA_AHCI_PXSERR_TRSTE_24 BIT24
+#define B_PCH_SATA_AHCI_PXSERR_TRSTE_23 BIT23
+#define B_PCH_SATA_AHCI_PXSERR_HANDSHAKE BIT22
+#define B_PCH_SATA_AHCI_PXSERR_CRC_ERROR BIT21
+#define B_PCH_SATA_AHCI_PXSERR_10B8B_DECERR BIT19
+#define B_PCH_SATA_AHCI_PXSERR_COMM_WAKE BIT18
+#define B_PCH_SATA_AHCI_PXSERR_PHY_ERROR BIT17
+#define B_PCH_SATA_AHCI_PXSERR_PHY_RDY_CHG BIT16
+#define B_PCH_SATA_AHCI_PXSERR_INTRNAL_ERR BIT11
+#define B_PCH_SATA_AHCI_PXSERR_PROTOCOL_ERR BIT10
+#define B_PCH_SATA_AHCI_PXSERR_PCDIE BIT9
+#define B_PCH_SATA_AHCI_PXSERR_TDIE BIT8
+#define B_PCH_SATA_AHCI_PXSERR_RCE BIT1
+#define B_PCH_SATA_AHCI_PXSERR_RDIE BIT0
+#define R_PCH_SATA_AHCI_P0SACT 0x134
+#define R_PCH_SATA_AHCI_P1SACT 0x1B4
+#define R_PCH_SATA_AHCI_P2SACT 0x234
+#define R_PCH_SATA_AHCI_P3SACT 0x2B4
+#define R_PCH_SATA_AHCI_P4SACT 0x334
+#define R_PCH_SATA_AHCI_P5SACT 0x3B4
+#define R_PCH_SATA_AHCI_P6SACT 0x434
+#define B_PCH_SATA_AHCI_PXSACT_DS 0xFFFFFFFF
+#define R_PCH_SATA_AHCI_P0CI 0x138
+#define R_PCH_SATA_AHCI_P1CI 0x1B8
+#define R_PCH_SATA_AHCI_P2CI 0x238
+#define R_PCH_SATA_AHCI_P3CI 0x2B8
+#define R_PCH_SATA_AHCI_P4CI 0x338
+#define R_PCH_SATA_AHCI_P5CI 0x3B8
+#define R_PCH_SATA_AHCI_P6CI 0x438
+#define B_PCH_SATA_AHCI_PXCI 0xFFFFFFFF
+
+//
+// SATA AHCI Device ID macros
+//
+#define IS_PCH_H_SATA_AHCI_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI_A0) || \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI) || \
+ (DeviceId == V_KBL_PCH_H_SATA_DEVICE_ID_D_AHCI) \
+ )
+
+#define IS_PCH_LP_SATA_AHCI_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_AHCI) \
+ )
+
+#define IS_PCH_SATA_AHCI_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_AHCI_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_AHCI_DEVICE_ID(DeviceId) \
+ )
+
+//
+// SATA RAID Device ID macros
+//
+#define IS_PCH_H_SATA_RAID_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID) || \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM) || \
+ (DeviceId == V_PCH_H_SATA_DEVICE_ID_D_RAID_ALTDIS) || \
+ (DeviceId == V_PCH_H_SATA_DEVICE_ID_D_RAID_RSTE) || \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_RRT) || \
+ (DeviceId == V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID) || \
+ (DeviceId == V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM) \
+ )
+
+
+#define IS_PCH_LP_SATA_RAID_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID) || \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID_ALTDIS) || \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID_PREM) || \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID_RRT) \
+ )
+
+#define IS_PCH_SATA_RAID_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_RAID_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_RAID_DEVICE_ID(DeviceId) \
+ )
+
+//
+// Combined SATA IDE/AHCI/RAID Device ID macros
+//
+#define IS_PCH_H_SATA_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_AHCI_DEVICE_ID(DeviceId) || \
+ IS_PCH_H_SATA_RAID_DEVICE_ID(DeviceId) \
+ )
+
+#define IS_PCH_LP_SATA_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_LP_SATA_AHCI_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_RAID_DEVICE_ID(DeviceId) \
+ )
+#define IS_PCH_SATA_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_DEVICE_ID(DeviceId) \
+ )
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h
new file mode 100644
index 0000000000..b1872adbe6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h
@@ -0,0 +1,202 @@
+/** @file
+ Register names for PCH Storage and Communication Subsystem
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_SCS_H_
+#define _PCH_REGS_SCS_H_
+
+//
+// SCS eMMC Controller Registers (D30:F4)
+//
+#define PCI_DEVICE_NUMBER_PCH_SCS_EMMC 30
+#define PCI_FUNCTION_NUMBER_PCH_SCS_EMMC 4
+#define V_PCH_SCS_EMMC_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_SCS_EMMC_DEVICE_ID 0x9D2B
+
+//
+// SCS SDIO Controller Registers (D30:F5)
+//
+#define PCI_DEVICE_NUMBER_PCH_SCS_SDIO 30
+#define PCI_FUNCTION_NUMBER_PCH_SCS_SDIO 5
+#define V_PCH_SCS_SDIO_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_SCS_SDIO_DEVICE_ID 0x9D2C
+
+//
+// SCS SDCARD Controller Registers (D30:F6)
+//
+#define PCI_DEVICE_NUMBER_PCH_SCS_SDCARD 30
+#define PCI_FUNCTION_NUMBER_PCH_SCS_SDCARD 6
+#define V_PCH_SCS_SDCARD_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_SCS_SDCARD_DEVICE_ID 0x9D2D
+
+//
+// SCS Devices PCI Config Space Registers
+//
+#define R_PCH_SCS_DEV_PCS 0x84 ///< PME Control Status
+#define B_PCH_SCS_DEV_PCS_PMESTS BIT15 ///< PME Status
+#define B_PCH_SCS_DEV_PCS_PMEEN BIT8 ///< PME Enable
+#define B_PCH_SCS_DEV_PCS_NSS BIT3 ///< No Soft Reset
+#define B_PCH_SCS_DEV_PCS_PS (BIT1 | BIT0) ///< Power State
+#define B_PCH_SCS_DEV_PCS_PS_D3HOT (BIT1 | BIT0) ///< Power State: D3Hot State
+#define R_PCH_SCS_DEV_PG_CONFIG 0xA2 ///< PG Config
+#define B_PCH_SCS_DEV_PG_CONFIG_SE BIT3 ///< Sleep Enable
+#define B_PCH_SCS_DEV_PG_CONFIG_PGE BIT2 ///< PG Enable
+#define B_PCH_SCS_DEV_PG_CONFIG_I3E BIT1 ///< I3 Enable
+#define B_PCH_SCS_DEV_PG_CONFIG_PMCRE BIT0 ///< PMC Request Enable
+#define V_PCH_SCS_DEV_BAR0_SIZE 0x1000 ///< BAR0 size
+//
+// SCS Devices MMIO Space Register
+//
+#define R_PCH_SCS_DEV_MEM_DMAADR 0x00
+#define R_PCH_SCS_DEV_MEM_BLKSZ 0x04
+#define R_PCH_SCS_DEV_MEM_BLKCNT 0x06
+#define R_PCH_SCS_DEV_MEM_CMDARG 0x08
+#define R_PCH_SCS_DEV_MEM_XFRMODE 0x0C
+#define B_PCH_SCS_DEV_MEM_XFRMODE_DMA_EN BIT0
+#define B_PCH_SCS_DEV_MEM_XFRMODE_BLKCNT_EN BIT1
+#define B_PCH_SCS_DEV_MEM_XFRMODE_AUTOCMD_EN_MASK (BIT2 | BIT3)
+#define V_PCH_SCS_DEV_MEM_XFRMODE_AUTOCMD12_EN 1
+#define B_PCH_SCS_DEV_MEM_XFRMODE_DATA_TRANS_DIR BIT4 ///< 1: Read (Card to Host), 0: Write (Host to Card)
+#define B_PCH_SCS_DEV_MEM_XFRMODE_MULTI_SINGLE_BLK BIT5 ///< 1: Multiple Block, 0: Single Block
+#define R_PCH_SCS_DEV_MEM_SDCMD 0x0E
+#define B_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_MASK (BIT0 | BIT1)
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_NO_RESP 0
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP136 1
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48 2
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48_CHK 3
+#define B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN BIT3
+#define B_PCH_SCS_DEV_MEM_SDCMD_CMD_INDEX_CHECK_EN BIT4
+#define B_PCH_SCS_DEV_MEM_SDCMD_DATA_PRESENT_SEL BIT5
+#define R_PCH_SCS_DEV_MEM_RESP 0x10
+#define R_PCH_SCS_DEV_MEM_BUFDATAPORT 0x20
+#define R_PCH_SCS_DEV_MEM_PSTATE 0x24
+#define B_PCH_SCS_DEV_MEM_PSTATE_DAT0 BIT20
+#define R_PCH_SCS_DEV_MEM_PWRCTL 0x29
+#define R_PCH_SCS_DEV_MEM_CLKCTL 0x2C
+#define R_PCH_SCS_DEV_MEM_TIMEOUT_CTL 0x2E ///< Timeout Control
+#define B_PCH_SCS_DEV_MEM_TIMEOUT_CTL_DTCV 0x0F ///< Data Timeout Counter Value
+#define R_PCH_SCS_DEV_MEM_SWRST 0x2F
+#define B_PCH_SCS_DEV_MEM_SWRST_CMDLINE BIT1
+#define B_PCH_SCS_DEV_MEM_SWRST_DATALINE BIT2
+#define R_PCH_SCS_DEV_MEM_NINTSTS 0x30
+#define B_PCH_SCS_DEV_MEM_NINTSTS_MASK 0xFFFF
+#define B_PCH_SCS_DEV_MEM_NINTSTS_CLEAR_MASK 0x60FF
+#define B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE BIT0
+#define B_PCH_SCS_DEV_MEM_NINTSTS_TRANSFER_COMPLETE BIT1
+#define B_PCH_SCS_DEV_MEM_NINTSTS_DMA_INTERRUPT BIT3
+#define B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR BIT5
+#define R_PCH_SCS_DEV_MEM_ERINTSTS 0x32
+#define B_PCH_SCS_DEV_MEM_ERINTSTS_MASK 0x13FF
+#define B_PCH_SCS_DEV_MEM_ERINTSTS_CLEAR_MASK 0x13FF
+#define R_PCH_SCS_DEV_MEM_NINTEN 0x34
+#define B_PCH_SCS_DEV_MEM_NINTEN_MASK 0x7FFF
+#define R_PCH_SCS_DEV_MEM_ERINTEN 0x36
+#define B_PCH_SCS_DEV_MEM_ERINTEN_MASK 0x13FF
+#define R_PCH_SCS_DEV_MEM_NINTSIGNEN 0x38
+#define B_PCH_SCS_DEV_MEM_NINTSIGNEN_MASK 0x7FFF
+#define R_PCH_SCS_DEV_MEM_ERINTSIGNEN 0x3A
+#define B_PCH_SCS_DEV_MEM_ERINTSIGNEN_MASK 0x13FF
+#define R_PCH_SCS_DEV_MEM_HOST_CTL2 0x3E
+#define B_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_MASK (BIT0 | BIT1 | BIT2)
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_HS400 5
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_DDR50 4
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR104 3
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR25 1
+#define R_PCH_SCS_DEV_MEM_CAP1 0x40
+#define R_PCH_SCS_DEV_MEM_CAP2 0x44
+#define B_PCH_SCS_DEV_MEM_CAP2_HS400_SUPPORT BIT31
+#define B_PCH_SCS_DEV_MEM_CAP2_SDR104_SUPPORT BIT1
+#define R_PCH_SCS_DEV_MEM_CESHC2 0x3C ///< Auto CMD12 Error Status Register & Host Control 2
+#define B_PCH_SCS_DEV_MEM_CESHC2_ASYNC_INT BIT30 ///< Asynchronous Interrupt Enable
+#define R_PCH_SCS_DEV_MEM_CAP_BYPASS_CONTROL 0x810
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_CONTROL_EN 0x5A
+#define R_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1 0x814
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_EMMC_DEFAULTS 0x3C80EB1E
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SDIO_DEFAULTS 0x1C80EF1E
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SDCARD_DEFAULTS 0x1C80E75C
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_HS400 BIT29
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMEOUT_CLK_FREQ (BIT27 | BIT26 | BIT25 | BIT24 | BIT23 | BIT22)
+#define N_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMEOUT_CLK_FREQ 22
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMEOUT_CLK_FREQ 0x1
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMER_COUNT (BIT20 | BIT19 | BIT18 | BIT17)
+#define N_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMER_COUNT 17
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMER_COUNT 0x8
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SLOT_TYPE (BIT12 | BIT11)
+#define N_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SLOT_TYPE 11
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SLOT_TYPE_EMBEDDED 0x1
+#define R_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2 0x818
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2_EMMC_DEFAULTS 0x040040C8
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2_SDIO_DEFAULTS 0x040000C8
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2_SDCARD_DEFAULTS 0x040000C8
+#define R_PCH_SCS_DEV_MEM_TX_CMD_DLL_CNTL1 0x820
+#define R_PCH_SCS_DEV_MEM_TX_CMD_DLL_CNTL2 0x80C
+#define R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1 0x824
+#define R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL2 0x828
+#define R_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL1 0x82C
+#define R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL 0x830
+#define R_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2 0x834
+#define N_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX 16
+#define V_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX_CLK_AUTO 0x2
+#define V_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX_CLK_BEFORE 0x1
+#define V_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX_CLK_AFTER 0x0
+
+//
+// SCS Private Configuration Space Registers
+//
+#define R_PCH_PCR_SCS_IOSFCTL 0x00 ///< IOSF Control
+#define B_PCH_PCR_SCS_IOSFCTL_NSNPDIS BIT7 ///< Non-Snoop Disable
+#define B_PCH_PCR_SCS_IOSFCTL_MAX_RD_PEND (BIT3 | BIT2 | BIT1 | BIT0) ///< Max upstream pending reads
+#define R_PCH_PCR_SCS_OCPCTL 0x10 ///< OCP Control
+#define B_PCH_PCR_SCS_OCPCTL_NPEN BIT0 ///< Downstream non-posted memory write capability
+#define R_PCH_PCR_SCS_PMCTL 0x1D0 ///< Power Management Control
+#define R_PCH_PCR_SCS_PCICFGCTR_EMMC 0x200 ///< PCI Configuration Control 1 - eMMC
+#define R_PCH_PCR_SCS_PCICFGCTR_SDIO 0x204 ///< PCI Configuration Control 2 - SDIO
+#define R_PCH_PCR_SCS_PCICFGCTR_SDCARD 0x208 ///< PCI Configuration Control 3 - SD Card
+#define B_PCH_PCR_SCS_PCICFGCTR_PCI_IRQ 0x0FF00000 ///< PCI IRQ number
+#define N_PCH_PCR_SCS_PCICFGCTR_PCI_IRQ 20
+#define B_PCH_PCR_SCS_PCICFGCTR_ACPI_IRQ 0x000FF000 ///< ACPI IRQ number
+#define N_PCH_PCR_SCS_PCICFGCTR_ACPI_IRQ 12
+#define B_PCH_PCR_SCS_PCICFGCTR_IPIN1 (BIT11 | BIT10 | BIT9 | BIT8) ///< Interrupt Pin
+#define N_PCH_PCR_SCS_PCICFGCTR_IPIN1 8
+#define B_PCH_PCR_SCS_PCICFGCTR_BAR1DIS BIT7 ///< BAR 1 Disable
+#define B_PCH_PCR_SCS_PCICFGCTR_PS 0x7C ///< PME Support
+#define B_PCH_PCR_SCS_PCICFGCTR_ACPI_INT_EN BIT1 ///< ACPI Interrupt Enable
+#define B_PCH_PCR_SCS_PCICFGCTR_PCI_CFG_DIS BIT0 ///< PCI Configuration Space Disable
+
+#define R_PCH_PCR_SCS_GPPRVRW1 0x600 ///< Clock Gating Control
+#define R_PCH_PCR_SCS_GPPRVRW2 0x604 ///< Host Controller Disable
+#define B_PCH_PCR_SCS_GPPRVRW2_EMMC_DIS BIT1 ///< eMMC Host Controller Disable
+#define B_PCH_PCR_SCS_GPPRVRW2_SDIO_SDCARD_DIS BIT2 ///< 1: SDIO Host Controller Disable, 0: SDCARD Host Controller Disable
+#define R_PCH_PCR_SCS_GPPRVRW6 0x614 ///< 1.8V Signal Select Delay Control
+#define V_PCH_PCR_SCS_GPPRVRW6_1P8_SEL_DELAY 0x7F ///< Rcomp SDCARD 10ms delay during switch
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h
new file mode 100644
index 0000000000..461b935fde
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h
@@ -0,0 +1,325 @@
+/** @file
+ Register names for PCH Serial IO Controllers
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_SERIAL_IO_
+#define _PCH_REGS_SERIAL_IO_
+
+
+//
+// Serial IO I2C0 Controller Registers (D21:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0 0
+#define V_PCH_LP_SERIAL_IO_I2C0_DEVICE_ID 0x9D60
+#define V_SKL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID 0xA160
+#define V_KBL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID 0xA2E0
+
+//
+// Serial IO I2C1 Controller Registers (D21:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1 1
+#define V_PCH_LP_SERIAL_IO_I2C1_DEVICE_ID 0x9D61
+#define V_SKL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID 0xA161
+#define V_KBL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID 0xA2E1
+
+//
+// Serial IO I2C2 Controller Registers (D21:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2 2
+#define V_PCH_LP_SERIAL_IO_I2C2_DEVICE_ID 0x9D62
+#define V_SKL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID 0xA162
+#define V_KBL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID 0xA2E2
+
+//
+// Serial IO I2C3 Controller Registers (D21:F3)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3 3
+#define V_PCH_LP_SERIAL_IO_I2C3_DEVICE_ID 0x9D63
+#define V_SKL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID 0xA163
+#define V_KBL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID 0xA2E3
+
+//
+// Serial IO I2C4 Controller Registers (D25:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4 2
+#define V_PCH_LP_SERIAL_IO_I2C4_DEVICE_ID 0x9D64
+
+//
+// Serial IO I2C5 Controller Registers (D25:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5 1
+#define V_PCH_LP_SERIAL_IO_I2C5_DEVICE_ID 0x9D65
+
+//
+// Serial IO SPI0 Controller Registers (D30:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0 2
+#define V_PCH_LP_SERIAL_IO_SPI0_DEVICE_ID 0x9D29
+#define V_SKL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID 0xA129
+#define V_KBL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID 0xA2A9
+
+//
+// Serial IO SPI1 Controller Registers (D30:F3)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1 3
+#define V_PCH_LP_SERIAL_IO_SPI1_DEVICE_ID 0x9D2A
+#define V_SKL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID 0xA129
+#define V_KBL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID 0xA2AA
+
+//
+// Serial IO UART0 Controller Registers (D30:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0 0
+#define V_PCH_LP_SERIAL_IO_UART0_DEVICE_ID 0x9D27
+#define V_SKL_PCH_H_SERIAL_IO_UART0_DEVICE_ID 0xA127
+#define V_KBL_PCH_H_SERIAL_IO_UART0_DEVICE_ID 0xA2A7
+
+//
+// Serial IO UART1 Controller Registers (D30:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1 1
+#define V_PCH_LP_SERIAL_IO_UART1_DEVICE_ID 0x9D28
+#define V_SKL_PCH_H_SERIAL_IO_UART1_DEVICE_ID 0xA128
+#define V_KBL_PCH_H_SERIAL_IO_UART1_DEVICE_ID 0xA2A8
+
+//
+// Serial IO UART2 Controller Registers (D25:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2 0
+#define V_PCH_LP_SERIAL_IO_UART2_DEVICE_ID 0x9D66
+#define V_SKL_PCH_H_SERIAL_IO_UART2_DEVICE_ID 0xA166
+#define V_KBL_PCH_H_SERIAL_IO_UART2_DEVICE_ID 0xA2E6
+
+#define V_PCH_SERIAL_IO_DEV_MIN_FUN 0
+#define V_PCH_SERIAL_IO_DEV_MAX_FUN 5
+
+//
+// Serial IO Controllers General PCI Configuration Registers
+// registers accessed using PciD21FxRegBase + offset
+//
+#define R_PCH_SERIAL_IO_BAR0_LOW 0x10
+#define B_PCH_SERIAL_IO_BAR0_LOW_BAR 0xFFFFF000
+#define R_PCH_SERIAL_IO_BAR0_HIGH 0x14
+#define R_PCH_SERIAL_IO_BAR1_LOW 0x18
+#define B_PCH_SERIAL_IO_BAR1_LOW_BAR 0xFFFFF000
+#define R_PCH_SERIAL_IO_BAR1_HIGH 0x1C
+#define V_PCH_SERIAL_IO_BAR_SIZE (4 * 1024)
+#define N_PCH_SERIAL_IO_BAR_ALIGNMENT 12
+
+#define R_PCH_SERIAL_IO_PME_CTRL_STS 0x84
+#define B_PCH_SERIAL_IO_PME_CTRL_STS_PWR_ST (BIT1| BIT0)
+
+#define R_PCH_SERIAL_IO_D0I3MAXDEVPG 0xA0
+#define B_PCH_SERIAL_IO_D0I3MAXDEVPG_PMCRE BIT16
+#define B_PCH_SERIAL_IO_D0I3MAXDEVPG_I3E BIT17
+#define B_PCH_SERIAL_IO_D0I3MAXDEVPG_PGE BIT18
+
+#define R_PCH_SERIAL_IO_INTERRUPTREG 0x3C
+#define B_PCH_SERIAL_IO_INTERRUPTREG_INTLINE 0x000000FF
+
+//
+// Serial IO Controllers Private Registers
+// registers accessed : BAR0 + offset
+//
+#define R_PCH_SERIAL_IO_SSCR1 0x4
+#define B_PCH_SERIAL_IO_SSCR1_IFS BIT16
+
+#define R_PCH_SERIAL_IO_PPR_CLK 0x200
+#define B_PCH_SERIAL_IO_PPR_CLK_EN BIT0
+#define B_PCH_SERIAL_IO_PPR_CLK_UPDATE BIT31
+#define V_PCH_SERIAL_IO_PPR_CLK_M_DIV 0x30
+#define V_PCH_SERIAL_IO_PPR_CLK_N_DIV 0xC35
+
+#define R_PCH_SERIAL_IO_PPR_RESETS 0x204
+#define B_PCH_SERIAL_IO_PPR_RESETS_FUNC BIT0
+#define B_PCH_SERIAL_IO_PPR_RESETS_APB BIT1
+#define B_PCH_SERIAL_IO_PPR_RESETS_IDMA BIT2
+
+#define R_PCH_SERIAL_IO_ACTIVE_LTR 0x210
+#define R_PCH_SERIAL_IO_IDLE_LTR 0x214
+#define B_PCH_SERIAL_IO_LTR_SNOOP_VALUE 0x000003FF
+#define B_PCH_SERIAL_IO_LTR_SNOOP_SCALE 0x00001C00
+#define B_PCH_SERIAL_IO_LTR_SNOOP_REQUIREMENT BIT15
+
+#define R_PCH_SERIAL_IO_SPI_CS_CONTROL 0x224
+#define B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE BIT1
+#define B_PCH_SERIAL_IO_SPI_CS_CONTROL_MODE BIT0
+
+#define R_PCH_SERIAL_IO_REMAP_ADR_LOW 0x240
+#define R_PCH_SERIAL_IO_REMAP_ADR_HIGH 0x244
+
+#define R_PCH_SERIAL_IO_I2C_SDA_HOLD 0x7C
+#define V_PCH_SERIAL_IO_I2C_SDA_HOLD_VALUE 0x002C002C
+
+//
+// I2C Controller
+// Registers accessed through BAR0 + offset
+//
+#define R_IC_CON 0x00 // I2c Control
+#define B_IC_MASTER_MODE BIT0
+#define B_IC_RESTART_EN BIT5
+#define B_IC_SLAVE_DISABLE BIT6
+#define V_IC_SPEED_STANDARD 0x02
+#define V_IC_SPEED_FAST 0x04
+#define V_IC_SPEED_HIGH 0x06
+
+#define R_IC_TAR 0x04 // I2c Target Address
+#define B_IC_TAR_10BITADDR_MASTER BIT12
+
+#define R_IC_DATA_CMD 0x10 // I2c Rx/Tx Data Buffer and Command
+#define B_IC_CMD_READ BIT8 // 1 = read, 0 = write
+#define B_IC_CMD_STOP BIT9 // 1 = STOP
+#define B_IC_CMD_RESTART BIT10 // 1 = IC_RESTART_EN
+#define V_IC_WRITE_CMD_MASK 0xFF
+
+#define R_IC_SS_SCL_HCNT 0x14 // Standard Speed I2c Clock SCL High Count
+#define R_IC_SS_SCL_LCNT 0x18 // Standard Speed I2c Clock SCL Low Count
+#define R_IC_FS_SCL_HCNT 0x1C // Full Speed I2c Clock SCL High Count
+#define R_IC_FS_SCL_LCNT 0x20 // Full Speed I2c Clock SCL Low Count
+#define R_IC_HS_SCL_HCNT 0x24 // High Speed I2c Clock SCL High Count
+#define R_IC_HS_SCL_LCNT 0x28 // High Speed I2c Clock SCL Low Count
+#define R_IC_INTR_STAT 0x2C // I2c Inetrrupt Status
+#define R_IC_INTR_MASK 0x30 // I2c Interrupt Mask
+#define B_IC_INTR_GEN_CALL BIT11 // General call received
+#define B_IC_INTR_START_DET BIT10
+#define B_IC_INTR_STOP_DET BIT9
+#define B_IC_INTR_ACTIVITY BIT8
+#define B_IC_INTR_TX_ABRT BIT6 // Set on NACK
+#define B_IC_INTR_TX_EMPTY BIT4
+#define B_IC_INTR_TX_OVER BIT3
+#define B_IC_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold
+#define B_IC_INTR_RX_OVER BIT1
+#define B_IC_INTR_RX_UNDER BIT0
+#define R_IC_RAW_INTR_STAT ( 0x34) // I2c Raw Interrupt Status
+#define R_IC_RX_TL ( 0x38) // I2c Receive FIFO Threshold
+#define R_IC_TX_TL ( 0x3C) // I2c Transmit FIFO Threshold
+#define R_IC_CLR_INTR ( 0x40) // Clear Combined and Individual Interrupts
+#define R_IC_CLR_RX_UNDER ( 0x44) // Clear RX_UNDER Interrupt
+#define R_IC_CLR_RX_OVER ( 0x48) // Clear RX_OVERinterrupt
+#define R_IC_CLR_TX_OVER ( 0x4C) // Clear TX_OVER interrupt
+#define R_IC_CLR_RD_REQ ( 0x50) // Clear RD_REQ interrupt
+#define R_IC_CLR_TX_ABRT ( 0x54) // Clear TX_ABRT interrupt
+#define R_IC_CLR_RX_DONE ( 0x58) // Clear RX_DONE interrupt
+#define R_IC_CLR_ACTIVITY ( 0x5C) // Clear ACTIVITY interrupt
+#define R_IC_CLR_STOP_DET ( 0x60) // Clear STOP_DET interrupt
+#define R_IC_CLR_START_DET ( 0x64) // Clear START_DET interrupt
+#define R_IC_CLR_GEN_CALL ( 0x68) // Clear GEN_CALL interrupt
+#define R_IC_ENABLE ( 0x6C) // I2c Enable
+
+#define R_IC_STATUS 0x70 // I2c Status
+#define B_IC_STATUS_RFF BIT4 // RX FIFO is completely full
+#define B_IC_STATUS_RFNE BIT3 // RX FIFO is not empty
+#define B_IC_STATUS_TFE BIT2 // TX FIFO is completely empty
+#define B_IC_STATUS_TFNF BIT1 // TX FIFO is not full
+#define B_IC_STATUS_ACTIVITY BIT0 // Controller Activity Status.
+
+#define R_IC_TXFL R ( 0x74) // Transmit FIFO Level Register
+#define R_IC_RXFLR ( 0x78) // Receive FIFO Level Register
+#define R_IC_SDA_HOLD ( 0x7C)
+#define R_IC_TX_ABRT_SOURCE ( 0x80) // I2c Transmit Abort Status Register
+#define B_IC_TX_ABRT_7B_ADDR_NACK BIT0 // NACK on 7-bit address
+
+#define R_IC_SDA_SETUP ( 0x94) // I2c SDA Setup Register
+#define R_IC_ACK_GENERAL_CALL ( 0x98) // I2c ACK General Call Register
+#define R_IC_ENABLE_STATUS ( 0x9C) // I2c Enable Status Register
+#define B_IC_EN BIT0 // I2c enable status
+
+#define R_IC_CLK_GATE (0xC0)
+#define R_IC_COMP_PARAM ( 0xF4) // Component Parameter Register
+#define R_IC_COMP_VERSION ( 0xF8) // Component Version ID
+#define R_IC_COMP_TYPE ( 0xFC) // Component Type
+
+
+
+//
+// Bridge Private Configuration Registers
+// accessed only through SB messaging. SB access = SerialIo IOSF2OCP Bridge Port ID + offset
+//
+#define R_PCH_PCR_SERIAL_IO_PMCTL 0x1D0
+#define V_PCH_PCR_SERIAL_IO_PMCTL_PWR_GATING 0x3F
+
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRLx 0x200
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_N_OFFS 0x04
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL1 0x200 //I2C0
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL2 0x204 //I2C1
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL3 0x208 //I2C2
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL4 0x20C //I2C3
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL5 0x210 //I2C4
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL6 0x214 //I2C5
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL9 0x218 //UA00
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL10 0x21C //UA01
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL11 0x220 //UA02
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL13 0x224 //SPI0
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL14 0x228 //SPI1
+
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS BIT0
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN BIT1
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS BIT7
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_INT_PIN (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_PCR_SERIAL_IO_PCICFGCTRL_INT_PIN 8
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTA 0x01
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTB 0x02
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTC 0x03
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTD 0x04
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_IRQ 0x000FF000
+#define N_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_IRQ 12
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_IRQ 0x0FF00000
+#define N_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_IRQ 20
+
+#define R_PCH_PCR_SERIAL_IO_GPPRVRW2 0x604
+#define V_PCH_PCR_SERIAL_IO_GPPRVRW2_CLK_GATING (BIT11 | BIT1)
+
+#define R_PCH_PCR_SERIAL_IO_GPPRVRW7 0x618
+#define B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN BIT0
+#define B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART1_BYTE_ADDR_EN BIT1
+#define B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART2_BYTE_ADDR_EN BIT2
+
+//
+// Number of pins used by SerialIo controllers
+//
+#define PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER 2
+#define PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER 4
+#define PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL 2
+#define PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER 4
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h
new file mode 100644
index 0000000000..9682040879
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h
@@ -0,0 +1,149 @@
+/** @file
+ Register names for PCH Smbus Device.
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_SMBUS_H_
+#define _PCH_REGS_SMBUS_H_
+
+//
+// SMBus Controller Registers (D31:F4)
+//
+#define PCI_DEVICE_NUMBER_PCH_SMBUS 31
+#define PCI_FUNCTION_NUMBER_PCH_SMBUS 4
+#define R_PCH_SMBUS_BASE 0x20
+#define V_PCH_SMBUS_BASE_SIZE (1 << 5)
+#define B_PCH_SMBUS_BASE_BAR 0x0000FFE0
+#define R_PCH_SMBUS_HOSTC 0x40
+#define B_PCH_SMBUS_HOSTC_SPDWD BIT4
+#define B_PCH_SMBUS_HOSTC_SSRESET BIT3
+#define B_PCH_SMBUS_HOSTC_I2C_EN BIT2
+#define B_PCH_SMBUS_HOSTC_SMI_EN BIT1
+#define B_PCH_SMBUS_HOSTC_HST_EN BIT0
+#define R_PCH_SMBUS_TCOBASE 0x50
+#define B_PCH_SMBUS_TCOBASE_BAR 0x0000FFE0
+#define R_PCH_SMBUS_TCOCTL 0x54
+#define B_PCH_SMBUS_TCOCTL_TCO_BASE_EN BIT8
+#define B_PCH_SMBUS_TCOCTL_TCO_BASE_LOCK BIT0
+#define R_PCH_SMBUS_64 0x64
+#define R_PCH_SMBUS_80 0x80
+
+//
+// SMBus I/O Registers
+//
+#define R_PCH_SMBUS_HSTS 0x00 ///< Host Status Register R/W
+#define B_PCH_SMBUS_HBSY 0x01
+#define B_PCH_SMBUS_INTR 0x02
+#define B_PCH_SMBUS_DERR 0x04
+#define B_PCH_SMBUS_BERR 0x08
+#define B_PCH_SMBUS_FAIL 0x10
+#define B_PCH_SMBUS_SMBALERT_STS 0x20
+#define B_PCH_SMBUS_IUS 0x40
+#define B_PCH_SMBUS_BYTE_DONE_STS 0x80
+#define B_PCH_SMBUS_ERROR (B_PCH_SMBUS_DERR | B_PCH_SMBUS_BERR | B_PCH_SMBUS_FAIL)
+#define B_PCH_SMBUS_HSTS_ALL 0xFF
+#define R_PCH_SMBUS_HCTL 0x02 ///< Host Control Register R/W
+#define B_PCH_SMBUS_INTREN 0x01
+#define B_PCH_SMBUS_KILL 0x02
+#define B_PCH_SMBUS_SMB_CMD 0x1C
+#define V_PCH_SMBUS_SMB_CMD_QUICK 0x00
+#define V_PCH_SMBUS_SMB_CMD_BYTE 0x04
+#define V_PCH_SMBUS_SMB_CMD_BYTE_DATA 0x08
+#define V_PCH_SMBUS_SMB_CMD_WORD_DATA 0x0C
+#define V_PCH_SMBUS_SMB_CMD_PROCESS_CALL 0x10
+#define V_PCH_SMBUS_SMB_CMD_BLOCK 0x14
+#define V_PCH_SMBUS_SMB_CMD_IIC_READ 0x18
+#define V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS 0x1C
+#define B_PCH_SMBUS_LAST_BYTE 0x20
+#define B_PCH_SMBUS_START 0x40
+#define B_PCH_SMBUS_PEC_EN 0x80
+#define R_PCH_SMBUS_HCMD 0x03 ///< Host Command Register R/W
+#define R_PCH_SMBUS_TSA 0x04 ///< Transmit Slave Address Register R/W
+#define B_PCH_SMBUS_RW_SEL 0x01
+#define B_PCH_SMBUS_READ 0x01 // RW
+#define B_PCH_SMBUS_WRITE 0x00 // RW
+#define B_PCH_SMBUS_ADDRESS 0xFE
+#define R_PCH_SMBUS_HD0 0x05 ///< Data 0 Register R/W
+#define R_PCH_SMBUS_HD1 0x06 ///< Data 1 Register R/W
+#define R_PCH_SMBUS_HBD 0x07 ///< Host Block Data Register R/W
+#define R_PCH_SMBUS_PEC 0x08 ///< Packet Error Check Data Register R/W
+#define R_PCH_SMBUS_RSA 0x09 ///< Receive Slave Address Register R/W
+#define B_PCH_SMBUS_SLAVE_ADDR 0x7F
+#define R_PCH_SMBUS_SD 0x0A ///< Receive Slave Data Register R/W
+#define R_PCH_SMBUS_AUXS 0x0C ///< Auxiliary Status Register R/WC
+#define B_PCH_SMBUS_CRCE 0x01
+#define B_PCH_SMBUS_STCO 0x02 ///< SMBus TCO Mode
+#define R_PCH_SMBUS_AUXC 0x0D ///< Auxiliary Control Register R/W
+#define B_PCH_SMBUS_AAC 0x01
+#define B_PCH_SMBUS_E32B 0x02
+#define R_PCH_SMBUS_SMLC 0x0E ///< SMLINK Pin Control Register R/W
+#define B_PCH_SMBUS_SMLINK0_CUR_STS 0x01
+#define B_PCH_SMBUS_SMLINK1_CUR_STS 0x02
+#define B_PCH_SMBUS_SMLINK_CLK_CTL 0x04
+#define R_PCH_SMBUS_SMBC 0x0F ///< SMBus Pin Control Register R/W
+#define B_PCH_SMBUS_SMBCLK_CUR_STS 0x01
+#define B_PCH_SMBUS_SMBDATA_CUR_STS 0x02
+#define B_PCH_SMBUS_SMBCLK_CTL 0x04
+#define R_PCH_SMBUS_SSTS 0x10 ///< Slave Status Register R/WC
+#define B_PCH_SMBUS_HOST_NOTIFY_STS 0x01
+#define R_PCH_SMBUS_SCMD 0x11 ///< Slave Command Register R/W
+#define B_PCH_SMBUS_HOST_NOTIFY_INTREN 0x01
+#define B_PCH_SMBUS_HOST_NOTIFY_WKEN 0x02
+#define B_PCH_SMBUS_SMBALERT_DIS 0x04
+#define R_PCH_SMBUS_NDA 0x14 ///< Notify Device Address Register RO
+#define B_PCH_SMBUS_DEVICE_ADDRESS 0xFE
+#define R_PCH_SMBUS_NDLB 0x16 ///< Notify Data Low Byte Register RO
+#define R_PCH_SMBUS_NDHB 0x17 ///< Notify Data High Byte Register RO
+
+//
+// SMBus Private Config Registers
+// (PID:SMB)
+//
+#define R_PCH_PCR_SMBUS_TCOCFG 0x00 ///< TCO Configuration register
+#define B_PCH_PCR_SMBUS_TCOCFG_IE BIT7 ///< TCO IRQ Enable
+#define B_PCH_PCR_SMBUS_TCOCFG_IS (BIT2 | BIT1 | BIT0) ///< TCO IRQ Select
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_9 0x00
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_10 0x01
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_11 0x02
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_20 0x04 ///< only if APIC enabled
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_21 0x05 ///< only if APIC enabled
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_22 0x06 ///< only if APIC enabled
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_23 0x07 ///< only if APIC enabled
+#define R_PCH_PCR_SMBUS_SMBTM 0x04 ///< SMBus Test Mode
+#define B_PCH_PCR_SMBUS_SMBTM_SMBCT BIT1 ///< SMBus Counter
+#define B_PCH_PCR_SMBUS_SMBTM_SMBDG BIT0 ///< SMBus Deglitch
+#define R_PCH_PCR_SMBUS_SCTM 0x08 ///< Short Counter Test Mode
+#define B_PCH_PCR_SMBUS_SCTM_SSU BIT31 ///< Simulation Speed-Up
+#define R_PCH_PCR_SMBUS_GC 0x0C ///< General Control
+#define B_PCH_PCR_SMBUS_GC_FD BIT0 ///< Function Disable
+#define B_PCH_PCR_SMBUS_GC_NR BIT1 ///< No Reboot
+#define B_PCH_PCR_SMBUS_GC_SMBSCGE BIT2 ///< SMB Static Clock Gating Enable
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h
new file mode 100644
index 0000000000..f43c676797
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h
@@ -0,0 +1,309 @@
+/** @file
+ Register names for PCH SPI device.
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_SPI_H_
+#define _PCH_REGS_SPI_H_
+
+//
+// SPI Registers (D31:F5)
+//
+
+#define PCI_DEVICE_NUMBER_PCH_SPI 31
+#define PCI_FUNCTION_NUMBER_PCH_SPI 5
+
+#define R_PCH_SPI_BAR0 0x10
+#define B_PCH_SPI_BAR0_MASK 0x0FFF
+
+#define R_PCH_SPI_BDE 0xD8
+#define B_PCH_SPI_BDE_F8 0x8000
+#define B_PCH_SPI_BDE_F0 0x4000
+#define B_PCH_SPI_BDE_E8 0x2000
+#define B_PCH_SPI_BDE_E0 0x1000
+#define B_PCH_SPI_BDE_D8 0x0800
+#define B_PCH_SPI_BDE_D0 0x0400
+#define B_PCH_SPI_BDE_C8 0x0200
+#define B_PCH_SPI_BDE_C0 0x0100
+#define B_PCH_SPI_BDE_LEG_F 0x0080
+#define B_PCH_SPI_BDE_LEG_E 0x0040
+#define B_PCH_SPI_BDE_70 0x0008
+#define B_PCH_SPI_BDE_60 0x0004
+#define B_PCH_SPI_BDE_50 0x0002
+#define B_PCH_SPI_BDE_40 0x0001
+
+#define R_PCH_SPI_BC 0xDC
+#define S_PCH_SPI_BC 4
+#define N_PCH_SPI_BC_ASE_BWP 11
+#define B_PCH_SPI_BC_ASE_BWP BIT11
+#define N_PCH_SPI_BC_ASYNC_SS 10
+#define B_PCH_SPI_BC_ASYNC_SS BIT10
+#define B_PCH_SPI_BC_OSFH BIT9 ///< OS Function Hide
+#define N_PCH_SPI_BC_SYNC_SS 8
+#define B_PCH_SPI_BC_SYNC_SS BIT8
+#define B_PCH_SPI_BC_BILD BIT7
+#define B_PCH_SPI_BC_BBS BIT6 ///< Boot BIOS strap
+#define N_PCH_SPI_BC_BBS 6
+#define V_PCH_SPI_BC_BBS_SPI 0 ///< Boot BIOS strapped to SPI
+#define V_PCH_SPI_BC_BBS_LPC 1 ///< Boot BIOS strapped to LPC
+#define B_PCH_SPI_BC_EISS BIT5 ///< Enable InSMM.STS
+#define B_PCH_SPI_BC_TSS BIT4
+#define B_PCH_SPI_BC_SRC (BIT3 | BIT2)
+#define N_PCH_SPI_BC_SRC 2
+#define V_PCH_SPI_BC_SRC_PREF_EN_CACHE_EN 0x02 ///< Prefetching and Caching enabled
+#define V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_DIS 0x01 ///< No prefetching and no caching
+#define V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_EN 0x00 ///< No prefetching, but caching enabled
+#define B_PCH_SPI_BC_LE BIT1 ///< Lock Enable
+#define N_PCH_SPI_BC_BLE 1
+#define B_PCH_SPI_BC_WPD BIT0 ///< Write Protect Disable
+
+//
+// BIOS Flash Program Registers (based on SPI_BAR0)
+//
+#define R_PCH_SPI_BFPR 0x00 ///< BIOS Flash Primary Region Register(32bits), which is RO and contains the same value from FREG1
+#define B_PCH_SPI_BFPR_PRL 0x7FFF0000 ///< BIOS Flash Primary Region Limit mask
+#define N_PCH_SPI_BFPR_PRL 16 ///< BIOS Flash Primary Region Limit bit position
+#define B_PCH_SPI_BFPR_PRB 0x00007FFF ///< BIOS Flash Primary Region Base mask
+#define N_PCH_SPI_BFPR_PRB 0 ///< BIOS Flash Primary Region Base bit position
+#define R_PCH_SPI_HSFSC 0x04 ///< Hardware Sequencing Flash Status and Control Register(32bits)
+#define B_PCH_SPI_HSFSC_FSMIE BIT31 ///< Flash SPI SMI# Enable
+#define B_PCH_SPI_HSFSC_FDBC_MASK 0x3F000000 ///< Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1.
+#define N_PCH_SPI_HSFSC_FDBC 24
+#define B_PCH_SPI_HSFSC_CYCLE_MASK 0x001E0000 ///< Flash Cycle.
+#define N_PCH_SPI_HSFSC_CYCLE 17
+#define V_PCH_SPI_HSFSC_CYCLE_READ 0 ///< Flash Cycle Read
+#define V_PCH_SPI_HSFSC_CYCLE_WRITE 2 ///< Flash Cycle Write
+#define V_PCH_SPI_HSFSC_CYCLE_4K_ERASE 3 ///< Flash Cycle 4K Block Erase
+#define V_PCH_SPI_HSFSC_CYCLE_64K_ERASE 4 ///< Flash Cycle 64K Sector Erase
+#define V_PCH_SPI_HSFSC_CYCLE_READ_SFDP 5 ///< Flash Cycle Read SFDP
+#define V_PCH_SPI_HSFSC_CYCLE_READ_JEDEC_ID 6 ///< Flash Cycle Read JEDEC ID
+#define V_PCH_SPI_HSFSC_CYCLE_WRITE_STATUS 7 ///< Flash Cycle Write Status
+#define V_PCH_SPI_HSFSC_CYCLE_READ_STATUS 8 ///< Flash Cycle Read Status
+#define B_PCH_SPI_HSFSC_CYCLE_FGO BIT16 ///< Flash Cycle Go.
+#define B_PCH_SPI_HSFSC_FLOCKDN BIT15 ///< Flash Configuration Lock-Down
+#define B_PCH_SPI_HSFSC_FDV BIT14 ///< Flash Descriptor Valid, once valid software can use hareware sequencing regs
+#define B_PCH_SPI_HSFSC_FDOPSS BIT13 ///< Flash Descriptor Override Pin-Strap Status
+#define B_PCH_SPI_HSFSC_PRR34_LOCKDN BIT12 ///< PRR3 PRR4 Lock-Down
+#define B_PCH_SPI_HSFSC_SAF_CE BIT8 ///< SAF ctype error
+#define B_PCH_SPI_HSFSC_SAF_MODE_ACTIVE BIT7 ///< Indicates flash is attached either directly to the PCH via the SPI bus or EC/BMC
+#define B_PCH_SPI_HSFSC_SAF_LE BIT6 ///< SAF link error
+#define B_PCH_SPI_HSFSC_SCIP BIT5 ///< SPI cycle in progress
+#define B_PCH_SPI_HSFSC_SAF_DLE BIT4 ///< SAF Data length error
+#define B_PCH_SPI_HSFSC_SAF_ERROR BIT3 ///< SAF Error
+#define B_PCH_SPI_HSFSC_AEL BIT2 ///< Access Error Log
+#define B_PCH_SPI_HSFSC_FCERR BIT1 ///< Flash Cycle Error
+#define B_PCH_SPI_HSFSC_FDONE BIT0 ///< Flash Cycle Done
+#define R_PCH_SPI_FADDR 0x08 ///< SPI Flash Address
+#define B_PCH_SPI_FADDR_MASK 0x07FFFFFF ///< SPI Flash Address Mask (0~26bit)
+#define R_PCH_SPI_DLOCK 0x0C ///< Discrete Lock Bits
+#define B_PCH_SPI_DLOCK_PR0LOCKDN BIT8 ///< PR0LOCKDN
+#define R_PCH_SPI_FDATA00 0x10 ///< SPI Data 00 (32 bits)
+#define R_PCH_SPI_FDATA01 0x14 ///< SPI Data 01
+#define R_PCH_SPI_FDATA02 0x18 ///< SPI Data 02
+#define R_PCH_SPI_FDATA03 0x1C ///< SPI Data 03
+#define R_PCH_SPI_FDATA04 0x20 ///< SPI Data 04
+#define R_PCH_SPI_FDATA05 0x24 ///< SPI Data 05
+#define R_PCH_SPI_FDATA06 0x28 ///< SPI Data 06
+#define R_PCH_SPI_FDATA07 0x2C ///< SPI Data 07
+#define R_PCH_SPI_FDATA08 0x30 ///< SPI Data 08
+#define R_PCH_SPI_FDATA09 0x34 ///< SPI Data 09
+#define R_PCH_SPI_FDATA10 0x38 ///< SPI Data 10
+#define R_PCH_SPI_FDATA11 0x3C ///< SPI Data 11
+#define R_PCH_SPI_FDATA12 0x40 ///< SPI Data 12
+#define R_PCH_SPI_FDATA13 0x44 ///< SPI Data 13
+#define R_PCH_SPI_FDATA14 0x48 ///< SPI Data 14
+#define R_PCH_SPI_FDATA15 0x4C ///< SPI Data 15
+#define R_PCH_SPI_FRAP 0x50 ///< Flash Region Access Permisions Register
+#define B_PCH_SPI_FRAP_BRWA_MASK 0x0000FF00 ///< BIOS Region Write Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define N_PCH_SPI_FRAP_BRWA 8 ///< BIOS Region Write Access bit position
+#define B_PCH_SPI_FRAP_BRRA_MASK 0x000000FF ///< BIOS Region Read Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define B_PCH_SPI_FRAP_BMRAG_MASK 0x00FF0000 ///< BIOS Master Read Access Grant
+#define B_PCH_SPI_FRAP_BMWAG_MASK 0xFF000000 ///< BIOS Master Write Access Grant
+#define R_PCH_SPI_FREG0_FLASHD 0x54 ///< Flash Region 0(Flash Descriptor)(32bits)
+#define R_PCH_SPI_FREG1_BIOS 0x58 ///< Flash Region 1(BIOS)(32bits)
+#define R_PCH_SPI_FREG2_ME 0x5C ///< Flash Region 2(ME)(32bits)
+#define R_PCH_SPI_FREG3_GBE 0x60 ///< Flash Region 3(GbE)(32bits)
+#define R_PCH_SPI_FREG4_PLATFORM_DATA 0x64 ///< Flash Region 4(Platform Data)(32bits)
+#define R_PCH_SPI_FREG5_DER 0x68 ///< Flash Region 5(Device Expansion Region)(32bits)
+#define S_PCH_SPI_FREGX 4 ///< Size of Flash Region register
+#define B_PCH_SPI_FREGX_LIMIT_MASK 0x7FFF0000 ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh
+#define N_PCH_SPI_FREGX_LIMIT 16 ///< Region limit bit position
+#define N_PCH_SPI_FREGX_LIMIT_REPR 12 ///< Region limit bit represents position
+#define B_PCH_SPI_FREGX_BASE_MASK 0x00007FFF ///< Flash Region Base, [14:0] represents [26:12]
+#define N_PCH_SPI_FREGX_BASE 0 ///< Region base bit position
+#define N_PCH_SPI_FREGX_BASE_REPR 12 ///< Region base bit represents position
+#define R_PCH_SPI_PR0 0x84 ///< Protected Region 0 Register
+#define R_PCH_SPI_PR1 0x88 ///< Protected Region 1 Register
+#define R_PCH_SPI_PR2 0x8C ///< Protected Region 2 Register
+#define R_PCH_SPI_PR3 0x90 ///< Protected Region 3 Register
+#define R_PCH_SPI_PR4 0x94 ///< Protected Region 4 Register
+#define S_PCH_SPI_PRX 4 ///< Protected Region X Register size
+#define B_PCH_SPI_PRX_WPE BIT31 ///< Write Protection Enable
+#define B_PCH_SPI_PRX_PRL_MASK 0x7FFF0000 ///< Protected Range Limit Mask, [30:16] here represents upper limit of address [26:12]
+#define N_PCH_SPI_PRX_PRL 16 ///< Protected Range Limit bit position
+#define B_PCH_SPI_PRX_RPE BIT15 ///< Read Protection Enable
+#define B_PCH_SPI_PRX_PRB_MASK 0x00007FFF ///< Protected Range Base Mask, [14:0] here represents base limit of address [26:12]
+#define N_PCH_SPI_PRX_PRB 0 ///< Protected Range Base bit position
+#define R_PCH_SPI_SFRAP 0xB0 ///< Secondary Flash Regions Access Permisions Register
+#define R_PCH_SPI_FDOC 0xB4 ///< Flash Descriptor Observability Control Register(32 bits)
+#define B_PCH_SPI_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) ///< Flash Descritor Section Select
+#define V_PCH_SPI_FDOC_FDSS_FSDM 0x0000 ///< Flash Signature and Descriptor Map
+#define V_PCH_SPI_FDOC_FDSS_COMP 0x1000 ///< Component
+#define V_PCH_SPI_FDOC_FDSS_REGN 0x2000 ///< Region
+#define V_PCH_SPI_FDOC_FDSS_MSTR 0x3000 ///< Master
+#define V_PCH_SPI_FDOC_FDSS_PCHS 0x4000 ///< PCH soft straps
+#define V_PCH_SPI_FDOC_FDSS_SFDP 0x5000 ///< SFDP Parameter Table
+#define B_PCH_SPI_FDOC_FDSI_MASK 0x0FFC ///< Flash Descriptor Section Index
+#define R_PCH_SPI_FDOD 0xB8 ///< Flash Descriptor Observability Data Register(32 bits)
+#define R_PCH_SPI_SFDP0_VSCC0 0xC4 ///< Vendor Specific Component Capabilities Register(32 bits)
+#define B_PCH_SPI_SFDPX_VSCCX_CPPTV BIT31 ///< Component Property Parameter Table Valid
+#define B_PCH_SPI_SFDP0_VSCC0_VCL BIT30 ///< Vendor Component Lock
+#define B_PCH_SPI_SFDPX_VSCCX_EO_64K BIT29 ///< 64k Erase valid (EO_64k_valid)
+#define B_PCH_SPI_SFDPX_VSCCX_EO_4K BIT28 ///< 4k Erase valid (EO_4k_valid)
+#define B_PCH_SPI_SFDPX_VSCCX_RPMC BIT27 ///< RPMC Supported
+#define B_PCH_SPI_SFDPX_VSCCX_DPD BIT26 ///< Deep Powerdown Supported
+#define B_PCH_SPI_SFDPX_VSCCX_SUSRES BIT25 ///< Suspend/Resume Supported
+#define B_PCH_SPI_SFDPX_VSCCX_SOFTRES BIT24 ///< Soft Reset Supported
+#define B_PCH_SPI_SFDPX_VSCCX_64k_EO_MASK 0x00FF0000 ///< 64k Erase Opcode (EO_64k)
+#define B_PCH_SPI_SFDPX_VSCCX_4k_EO_MASK 0x0000FF00 ///< 4k Erase Opcode (EO_4k)
+#define B_PCH_SPI_SFDPX_VSCCX_QER (BIT7 | BIT6 | BIT5) ///< Quad Enable Requirements
+#define B_PCH_SPI_SFDPX_VSCCX_WEWS BIT4 ///< Write Enable on Write Status
+#define B_PCH_SPI_SFDPX_VSCCX_WSR BIT3 ///< Write Status Required
+#define B_PCH_SPI_SFDPX_VSCCX_WG_64B BIT2 ///< Write Granularity, 0: 1 Byte; 1: 64 Bytes
+#define R_PCH_SPI_SFDP1_VSCC1 0xC8 ///< Vendor Specific Component Capabilities Register(32 bits)
+#define R_PCH_SPI_PINTX 0xCC ///< Parameter Table Index
+#define N_PCH_SPI_PINTX_SPT 14
+#define V_PCH_SPI_PINTX_SPT_CPT0 0x0 ///< Component 0 Property Parameter Table
+#define V_PCH_SPI_PINTX_SPT_CPT1 0x1 ///< Component 1 Property Parameter Table
+#define N_PCH_SPI_PINTX_HORD 12
+#define V_PCH_SPI_PINTX_HORD_SFDP 0x0 ///< SFDP Header
+#define V_PCH_SPI_PINTX_HORD_PT 0x1 ///< Parameter Table Header
+#define V_PCH_SPI_PINTX_HORD_DATA 0x2 ///< Data
+#define R_PCH_SPI_PTDATA 0xD0 ///< Parameter Table Data
+#define R_PCH_SPI_SBRS 0xD4 ///< SPI Bus Requester Status
+#define R_PCH_SPI_SSML 0xF0 ///< Set Strap Msg Lock
+#define B_PCH_SPI_SSML_SSL BIT0 ///< Set_Strap Lock
+#define R_PCH_SPI_SSMC 0xF4 ///< Set Strap Msg Control
+#define B_PCH_SPI_SSMC_SSMS BIT0 ///< Set_Strap Mux Select
+#define R_PCH_SPI_SSMD 0xF8 ///< Set Strap Msg Data
+//
+// @todo Follow up with EDS owner if it should be 3FFF or FFFF.
+//
+#define B_PCH_SPI_SRD_SSD 0x0000FFFF ///< Set_Strap Data
+//
+// Flash Descriptor Base Address Region (FDBAR) from Flash Region 0
+//
+#define R_PCH_SPI_FDBAR_FLVALSIG 0x00 ///< Flash Valid Signature
+#define V_PCH_SPI_FDBAR_FLVALSIG 0x0FF0A55A
+#define R_PCH_SPI_FDBAR_FLASH_MAP0 0x04
+#define B_PCH_SPI_FDBAR_FCBA 0x000000FF ///< Flash Component Base Address
+#define B_PCH_SPI_FDBAR_NC 0x00000300 ///< Number Of Components
+#define N_PCH_SPI_FDBAR_NC 8 ///< Number Of Components
+#define V_PCH_SPI_FDBAR_NC_1 0x00000000
+#define V_PCH_SPI_FDBAR_NC_2 0x00000100
+#define B_PCH_SPI_FDBAR_FRBA 0x00FF0000 ///< Flash Region Base Address
+#define B_PCH_SPI_FDBAR_NR 0x07000000 ///< Number Of Regions
+#define R_PCH_SPI_FDBAR_FLASH_MAP1 0x08
+#define B_PCH_SPI_FDBAR_FMBA 0x000000FF ///< Flash Master Base Address
+#define B_PCH_SPI_FDBAR_NM 0x00000700 ///< Number Of Masters
+#define B_PCH_SPI_FDBAR_FPSBA 0x00FF0000 ///< PCH Strap Base Address, [23:16] represents [11:4]
+#define N_PCH_SPI_FDBAR_FPSBA 16 ///< PCH Strap base Address bit position
+#define N_PCH_SPI_FDBAR_FPSBA_REPR 4 ///< PCH Strap base Address bit represents position
+#define B_PCH_SPI_FDBAR_PCHSL 0xFF000000 ///< PCH Strap Length, [31:24] represents number of Dwords
+#define N_PCH_SPI_FDBAR_PCHSL 24 ///< PCH Strap Length bit position
+#define R_PCH_SPI_FDBAR_FLASH_MAP2 0x0C
+#define B_PCH_SPI_FDBAR_FCPUSBA 0x000000FF ///< CPU Strap Base Address, [7:0] represents [11:4]
+#define N_PCH_SPI_FDBAR_FCPUSBA 0 ///< CPU Strap Base Address bit position
+#define N_PCH_SPI_FDBAR_FCPUSBA_REPR 4 ///< CPU Strap Base Address bit represents position
+#define B_PCH_SPI_FDBAR_CPUSL 0x0000FF00 ///< CPU Strap Length, [15:8] represents number of Dwords
+#define N_PCH_SPI_FDBAR_CPUSL 8 ///< CPU Strap Length bit position
+//
+// Flash Component Base Address (FCBA) from Flash Region 0
+//
+#define R_PCH_SPI_FCBA_FLCOMP 0x00 ///< Flash Components Register
+#define B_PCH_SPI_FLCOMP_RIDS_FREQ (BIT29 | BIT28 | BIT27) ///< Read ID and Read Status Clock Frequency
+#define B_PCH_SPI_FLCOMP_WE_FREQ (BIT26 | BIT25 | BIT24) ///< Write and Erase Clock Frequency
+#define B_PCH_SPI_FLCOMP_FRCF_FREQ (BIT23 | BIT22 | BIT21) ///< Fast Read Clock Frequency
+#define B_PCH_SPI_FLCOMP_FR_SUP BIT20 ///< Fast Read Support.
+#define B_PCH_SPI_FLCOMP_RC_FREQ (BIT19 | BIT18 | BIT17) ///< Read Clock Frequency.
+#define V_PCH_SPI_FLCOMP_FREQ_48MHZ 0x02
+#define V_PCH_SPI_FLCOMP_FREQ_30MHZ 0x04
+#define V_PCH_SPI_FLCOMP_FREQ_17MHZ 0x06
+#define B_PCH_SPI_FLCOMP_COMP1_MASK 0xF0 ///< Flash Component 1 Size MASK
+#define N_PCH_SPI_FLCOMP_COMP1 4 ///< Flash Component 1 Size bit position
+#define B_PCH_SPI_FLCOMP_COMP0_MASK 0x0F ///< Flash Component 0 Size MASK
+#define V_PCH_SPI_FLCOMP_COMP_512KB 0x80000
+//
+// Descriptor Upper Map Section from Flash Region 0
+//
+#define R_PCH_SPI_FLASH_UMAP1 0xEFC ///< Flash Upper Map 1
+#define B_PCH_SPI_FLASH_UMAP1_VTBA 0x000000FF ///< VSCC Table Base Address
+#define B_PCH_SPI_FLASH_UMAP1_VTL 0x0000FF00 ///< VSCC Table Length
+
+#define R_PCH_SPI_VTBA_JID0 0x00 ///< JEDEC-ID 0 Register
+#define S_PCH_SPI_VTBA_JID0 0x04
+#define B_PCH_SPI_VTBA_JID0_VID 0x000000FF
+#define B_PCH_SPI_VTBA_JID0_DID0 0x0000FF00
+#define B_PCH_SPI_VTBA_JID0_DID1 0x00FF0000
+#define N_PCH_SPI_VTBA_JID0_DID0 0x08
+#define N_PCH_SPI_VTBA_JID0_DID1 0x10
+#define R_PCH_SPI_VTBA_VSCC0 0x04
+#define S_PCH_SPI_VTBA_VSCC0 0x04
+
+
+//
+// SPI Private Configuration Space Registers
+//
+#define R_PCH_PCR_SPI_CLK_CTL 0xC004
+#define R_PCH_PCR_SPI_PWR_CTL 0xC008
+#define R_PCH_PCR_SPI_ESPI_SOFTSTRAPS 0xC210
+#define B_PCH_PCR_SPI_ESPI_SOFTSTRAPS_SLAVE BIT12
+
+//
+// MMP0
+//
+#define R_PCH_SPI_STRP_MMP0 0xC4 ///< MMP0 Soft strap offset
+#define B_PCH_SPI_STRP_MMP0 0x10 ///< MMP0 Soft strap bit
+
+
+#define R_PCH_SPI_STRP_SFDP 0xF0 ///< PCH Soft Strap SFDP
+#define B_PCH_SPI_STRP_SFDP_QIORE BIT3 ///< Quad IO Read Enable
+#define B_PCH_SPI_STRP_SFDP_QORE BIT2 ///< Quad Output Read Enable
+#define B_PCH_SPI_STRP_SFDP_DIORE BIT1 ///< Dual IO Read Enable
+#define B_PCH_SPI_STRP_SFDP_DORE BIT0 ///< Dual Output Read Enable
+
+//
+// Descriptor Record 0
+//
+#define R_PCH_SPI_STRP_DSCR_0 0x00 ///< PCH Soft Strap 0
+#define B_PCH_SPI_STRP_DSCR_0_PTT_SUPP BIT22 ///< PTT Supported
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h
new file mode 100644
index 0000000000..fe43d210ab
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h
@@ -0,0 +1,107 @@
+/** @file
+ Register names for PCH Thermal Device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_THERMAL_H_
+#define _PCH_REGS_THERMAL_H_
+
+//
+// Thermal Device Registers (D20:2)
+//
+#define PCI_DEVICE_NUMBER_PCH_THERMAL 20
+#define PCI_FUNCTION_NUMBER_PCH_THERMAL 2
+
+#define R_PCH_THERMAL_TBAR 0x10
+#define V_PCH_THERMAL_TBAR_SIZE (4 * 1024)
+#define N_PCH_THREMAL_TBAR_ALIGNMENT 12
+#define B_PCH_THERMAL_TBAR_MASK 0xFFFFF000
+#define R_PCH_THERMAL_TBARH 0x14
+#define R_PCH_THERMAL_TBARB 0x40
+#define V_PCH_THERMAL_TBARB_SIZE (4 * 1024)
+#define N_PCH_THREMAL_TBARB_ALIGNMENT 12
+#define B_PCH_THERMAL_SPTYPEN BIT0
+#define R_PCH_THERMAL_TBARBH 0x44
+#define B_PCH_THERMAL_TBARB_MASK 0xFFFFF000
+
+//
+// Thermal TBAR MMIO registers
+//
+#define R_PCH_TBAR_TSC 0x04
+#define B_PCH_TBAR_TSC_PLD BIT7
+#define B_PCH_TBAR_TSC_CPDE BIT0
+#define R_PCH_TBAR_TSS 0x06
+#define R_PCH_TBAR_TSEL 0x08
+#define B_PCH_TBAR_TSEL_PLD BIT7
+#define B_PCH_TBAR_TSEL_ETS BIT0
+#define R_PCH_TBAR_TSREL 0x0A
+#define R_PCH_TBAR_TSMIC 0x0C
+#define B_PCH_TBAR_TSMIC_PLD BIT7
+#define B_PCH_TBAR_TSMIC_SMIE BIT0
+#define R_PCH_TBAR_CTT 0x10
+#define R_PCH_TBAR_TAHV 0x14
+#define R_PCH_TBAR_TALV 0x18
+#define R_PCH_TBAR_TSPM 0x1C
+#define B_PCH_TBAR_TSPM_LTT (BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+#define V_PCH_TBAR_TSPM_LTT 0x0C8
+#define B_PCH_TBAR_TSPM_MAXTSST (BIT11 | BIT10 | BIT9)
+#define V_PCH_TBAR_TSPM_MAXTSST (0x4 << 9)
+#define B_PCH_TBAR_TSPM_MINTSST BIT12
+#define B_PCH_TBAR_TSPM_DTSSIC0 BIT13
+#define B_PCH_TBAR_TSPM_DTSSS0EN BIT14
+#define B_PCH_TBAR_TSPM_TSPMLOCK BIT15
+#define R_PCH_TBAR_TL 0x40
+#define B_PCH_TBAR_TL_LOCK BIT31
+#define B_PCH_TBAR_TL_TTEN BIT29
+#define R_PCH_TBAR_TL2 0x50
+#define R_PCH_TBAR_TL2_LOCK BIT15
+#define R_PCH_TBAR_TL2_PMCTEN BIT14
+#define R_PCH_TBAR_PHL 0x60
+#define B_PCH_TBAR_PHLE BIT15
+#define R_PCH_TBAR_PHLC 0x62
+#define B_PCH_TBAR_PHLC_LOCK BIT0
+#define R_PCH_TBAR_TAS 0x80
+#define R_PCH_TBAR_TSPIEN 0x82
+#define R_PCH_TBAR_TSGPEN 0x84
+#define B_PCH_TBAR_TL2_PMCTEN BIT14
+#define R_PCH_TBAR_A4 0xA4
+#define R_PCH_TBAR_C0 0xC0
+#define R_PCH_TBAR_C4 0xC4
+#define R_PCH_TBAR_C8 0xC8
+#define R_PCH_TBAR_CC 0xCC
+#define R_PCH_TBAR_D0 0xD0
+#define R_PCH_TBAR_E0 0xE0
+#define R_PCH_TBAR_E4 0xE4
+#define R_PCH_TBAR_E8 0xE8
+#define R_PCH_TBAR_TCFD 0xF0 ///< Thermal controller function disable
+#define B_PCH_TBAR_TCFD_TCD BIT0 ///< Thermal controller disable
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h
new file mode 100644
index 0000000000..513b022f08
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h
@@ -0,0 +1,140 @@
+/** @file
+ Register names for PCH TraceHub device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_REGS_TRACE_HUB_H_
+#define _PCH_REGS_TRACE_HUB_H_
+
+//
+// TraceHub Registers (D31:F7)
+//
+#define PCI_DEVICE_NUMBER_PCH_TRACE_HUB 31
+#define PCI_FUNCTION_NUMBER_PCH_TRACE_HUB 7
+
+#define R_PCH_TRACE_HUB_CSR_MTB_LBAR 0x10
+#define B_PCH_TRACE_HUB_CSR_MTB_RBAL 0xFFF00000
+#define R_PCH_TRACE_HUB_CSR_MTB_UBAR 0x14
+#define B_PCH_TRACE_HUB_CSR_MTB_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_SW_LBAR 0x18
+#define B_PCH_TRACE_HUB_SW_RBAL 0xFFE00000
+#define R_PCH_TRACE_HUB_SW_UBAR 0x1C
+#define B_PCH_TRACE_HUB_SW_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_RTIT_LBAR 0x20
+#define B_PCH_TRACE_HUB_RTIT_RBAL 0xFFFFFF00
+#define R_PCH_TRACE_HUB_RTIT_UBAR 0x24
+#define B_PCH_TRACE_HUB_RTIT_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_MSICID 0x40
+#define R_PCH_TRACE_HUB_MSINCP 0x41
+#define R_PCH_TRACE_HUB_MSIMC 0x42
+#define R_PCH_TRACE_HUB_MSILMA 0x44
+#define R_PCH_TRACE_HUB_MSIUMA 0x48
+#define R_PCH_TRACE_HUB_MSIMD 0x4C
+#define B_PCH_TRACE_HUB_FW_RBAL 0xFFFC0000
+#define B_PCH_TRACE_HUB_FW_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_DSC 0x80
+#define B_PCH_TRACE_HUB_BYP BIT0 //< TraceHub Bypass
+#define R_PCH_TRACE_HUB_DSS 0x81
+#define R_PCH_TRACE_HUB_ISTOT 0x84
+#define R_PCH_TRACE_HUB_ICTOT 0x88
+#define R_PCH_TRACE_HUB_IPAD 0x8C
+#define R_PCH_TRACE_HUB_DSD 0x90
+
+//
+// Offsets from CSR_MTB_BAR
+//
+#define R_PCH_TRACE_HUB_MTB_GTHOPT0 0x00
+#define B_PCH_TRACE_HUB_MTB_GTHOPT0_P0FLUSH BIT7
+#define B_PCH_TRACE_HUB_MTB_GTHOPT0_P1FLUSH BIT15
+#define V_PCH_TRACE_HUB_MTB_SWDEST_PTI 0x0A
+#define V_PCH_TRACE_HUB_MTB_SWDEST_MEMEXI 0x08
+#define V_PCH_TRACE_HUB_MTB_SWDEST_DISABLE 0x00
+#define R_PCH_TRACE_HUB_MTB_SWDEST_1 0x0C
+#define B_PCH_TRACE_HUB_MTB_SWDEST_CSE_1 0x0000000F
+#define B_PCH_TRACE_HUB_MTB_SWDEST_CSE_2 0x000000F0
+#define B_PCH_TRACE_HUB_MTB_SWDEST_CSE_3 0x00000F00
+#define B_PCH_TRACE_HUB_MTB_SWDEST_ISH_1 0x0000F000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_ISH_2 0x000F0000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_ISH_3 0x00F00000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_AUDIO 0x0F000000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_PMC 0xF0000000
+#define R_PCH_TRACE_HUB_MTB_SWDEST_2 0x10
+#define B_PCH_TRACE_HUB_MTB_SWDEST_FTH 0x0000000F
+#define R_PCH_TRACE_HUB_MTB_SWDEST_3 0x14
+#define B_PCH_TRACE_HUB_MTB_SWDEST_MAESTRO 0x00000F00
+#define B_PCH_TRACE_HUB_MTB_SWDEST_SKYCAM 0x0F000000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_AET 0xF0000000
+#define R_PCH_TRACE_HUB_MTB_SWDEST_4 0x18
+#define R_PCH_TRACE_HUB_MTB_MSC0CTL 0xA0100
+#define R_PCH_TRACE_HUB_MTB_MSC1CTL 0xA0200
+#define V_PCH_TRACE_HUB_MTB_MSCNMODE_DCI 0x2
+#define V_PCH_TRACE_HUB_MTB_MSCNMODE_DEBUG 0x3
+#define B_PCH_TRACE_HUB_MTB_MSCNLEN (BIT10 | BIT9 | BIT8)
+#define B_PCH_TRACE_HUB_MTB_MSCNMODE (BIT5 | BIT4)
+#define N_PCH_TRACE_HUB_MTB_MSCNMODE 0x4
+#define B_PCH_TRACE_HUB_MTB_MSCN_RD_HDR_OVRD BIT2
+#define B_PCH_TRACE_HUB_MTB_WRAPENN BIT1
+#define B_PCH_TRACE_HUB_MTB_MSCNEN BIT0
+#define R_PCH_TRACE_HUB_MTB_GTHSTAT 0xD4
+#define R_PCH_TRACE_HUB_MTB_SCR2 0xD8
+#define B_PCH_TRACE_HUB_MTB_SCR2_FCD BIT0
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF2 BIT2
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF3 BIT3
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF4 BIT4
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF5 BIT5
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF6 BIT6
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF7 BIT7
+#define R_PCH_TRACE_HUB_MTB_MSC0BAR 0xA0108
+#define R_PCH_TRACE_HUB_MTB_MSC0SIZE 0xA010C
+#define R_PCH_TRACE_HUB_MTB_MSC1BAR 0xA0208
+#define R_PCH_TRACE_HUB_MTB_MSC1SIZE 0xA020C
+#define R_PCH_TRACE_HUB_MTB_STREAMCFG1 0xA1000
+#define B_PCH_TRACE_HUB_MTB_STREAMCFG1_ENABLE BIT28
+#define R_PCH_TRACE_HUB_MTB_PTI_CTL 0x1C00
+#define B_PCH_TRACE_HUB_MTB_PTIMODESEL 0xF0
+#define B_PCH_TRACE_HUB_MTB_PTICLKDIV (BIT17 | BIT16)
+#define B_PCH_TRACE_HUB_MTB_PATGENMOD (BIT22 | BIT21 | BIT20)
+#define B_PCH_TRACE_HUB_MTB_PTI_EN BIT0
+#define R_PCH_TRACE_HUB_MTB_SCR 0xC8
+#define R_PCH_TRACE_HUB_MTB_GTH_FREQ 0xCC
+#define V_PCH_TRACE_HUB_MTB_SCR 0x00130000
+#define R_PCH_TRACE_HUB_CSR_MTB_SCRATCHPAD0 0xE0
+#define R_PCH_TRACE_HUB_CSR_MTB_SCRATCHPAD1 0xE4
+#define R_PCH_TRACE_HUB_CSR_MTB_SCRATCHPAD10 0xE40
+#define R_PCH_TRACE_HUB_MTB_CTPGCS 0x1C14
+#define B_PCH_TRACE_HUB_MTB_CTPEN BIT0
+#define V_PCH_TRACE_HUB_MTB_CHLCNT 0x80
+#define V_PCH_TRACE_HUB_MTB_STHMSTR 0x20
+#define R_PCH_TRACE_HUB_CSR_MTB_TSUCTRL 0x2000
+#define B_PCH_TRACE_HUB_CSR_MTB_TSUCTRL_CTCRESYNC BIT0
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h
new file mode 100644
index 0000000000..7dfe90815f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h
@@ -0,0 +1,490 @@
+/** @file
+ Register names for PCH USB devices
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_REGS_USB_H_
+#define _PCH_REGS_USB_H_
+
+//
+// USB3 (XHCI) related definitions
+//
+#define PCI_BUS_NUMBER_PCH_XHCI 0
+#define PCI_DEVICE_NUMBER_PCH_XHCI 20
+#define PCI_FUNCTION_NUMBER_PCH_XHCI 0
+
+//
+// XHCI PCI Config Space registers
+//
+#define R_PCH_XHCI_MEM_BASE 0x10
+#define R_PCH_XHCI_MEM_BASE_2 0x14
+#define V_PCH_XHCI_MEM_LENGTH 0x10000
+#define N_PCH_XHCI_MEM_SHIFT 32
+#define N_PCH_XHCI_MEM_ALIGN 16
+#define B_PCH_XHCI_MEM_ALIGN_MASK 0xFFFF
+
+#define R_PCH_XHCI_XHCC1 0x40
+#define B_PCH_XHCI_XHCC1_ACCTRL BIT31
+#define B_PCH_XHCI_XHCC1_RMTASERR BIT24
+#define B_PCH_XHCI_XHCC1_URD BIT23
+#define B_PCH_XHCI_XHCC1_URRE BIT22
+#define B_PCH_XHCI_XHCC1_IIL1E (BIT21 | BIT20 | BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_DIS 0
+#define V_PCH_XHCI_XHCC1_IIL1E_32 (BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_64 (BIT20)
+#define V_PCH_XHCI_XHCC1_IIL1E_128 (BIT20 | BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_256 (BIT21)
+#define V_PCH_XHCI_XHCC1_IIL1E_512 (BIT21 | BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_1024 (BIT21 | BIT20)
+#define V_PCH_XHCI_XHCC1_IIL1E_131072 (BIT21 | BIT20 | BIT19)
+#define B_PCH_XHCI_XHCC1_XHCIL1E BIT18
+#define B_PCH_XHCI_XHCC1_D3IL1E BIT17
+#define B_PCH_XHCI_XHCC1_UNPPA (BIT16 | BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_XHCI_XHCC1_SWAXHCI BIT11
+#define B_PCH_XHCI_XHCC1_L23HRAWC (BIT10 | BIT9 | BIT8)
+#define B_PCH_XHCI_XHCC1_UTAGCP (BIT7 | BIT6)
+#define B_PCH_XHCI_XHCC1_UDAGCNP (BIT5 | BIT4)
+#define B_PCH_XHCI_XHCC1_UDAGCCP (BIT3 | BIT2)
+#define B_PCH_XHCI_XHCC1_UDAGC (BIT1 | BIT0)
+
+#define R_PCH_XHCI_XHCC2 0x44
+#define B_PCH_XHCI_XHCC2_OCCFDONE BIT31
+#define B_PCH_XHCI_XHCC2_XHCUPRDROE BIT11
+#define B_PCH_XHCI_XHCC2_IOSFSRAD BIT10
+#define B_PCH_XHCI_XHCC2_SWACXIHB (BIT9 | BIT8)
+#define B_PCH_XHCI_XHCC2_SWADMIL1IHB (BIT7 | BIT6)
+#define B_PCH_XHCI_XHCC2_L1FP2CGWC (BIT5 | BIT4 | BIT3)
+#define B_PCH_XHCI_XHCC2_RDREQSZCTRL (BIT2 | BIT1 | BIT0)
+
+#define R_PCH_XHCI_XHCLKGTEN 0x50
+#define B_PCH_XHCI_XHCLKGTEN_SSLSE BIT26
+#define B_PCH_XHCI_XHCLKGTEN_USB2PLLSE BIT25
+#define B_PCH_XHCI_XHCLKGTEN_IOSFSTCGE BIT24
+#define B_PCH_XHCI_XHCLKGTEN_HSTCGE (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_XHCI_XHCLKGTEN_SSTCGE (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_XHCI_XHCLKGTEN_XHCIGEU3S BIT15
+#define B_PCH_XHCI_XHCLKGTEN_XHCFTCLKSE BIT14
+#define B_PCH_XHCI_XHCLKGTEN_XHCBBTCGIPISO BIT13
+#define B_PCH_XHCI_XHCLKGTEN_XHCHSTCGU2NRWE BIT12
+#define B_PCH_XHCI_XHCLKGTEN_XHCUSB2PLLSDLE (BIT11 | BIT10)
+#define B_PCH_XHCI_XHCLKGTEN_HSPLLSUE (BIT9 | BIT8)
+#define B_PCH_XHCI_XHCLKGTEN_SSPLLSUE (BIT7 | BIT6 | BIT5)
+#define B_PCH_XHCI_XHCLKGTEN_XHCBLCGE BIT4
+#define B_PCH_XHCI_XHCLKGTEN_HSLTCGE BIT3
+#define B_PCH_XHCI_XHCLKGTEN_SSLTCGE BIT2
+#define B_PCH_XHCI_XHCLKGTEN_IOSFBTCGE BIT1
+#define B_PCH_XHCI_XHCLKGTEN_IOSFGBLCGE BIT0
+
+#define R_PCH_XHCI_USB_RELNUM 0x60
+#define B_PCH_XHCI_USB_RELNUM 0xFF
+#define R_PCH_XHCI_FL_ADJ 0x61
+#define B_PCH_XHCI_FL_ADJ 0x3F
+#define R_PCH_XHCI_PWR_CAPID 0x70
+#define B_PCH_XHCI_PWR_CAPID 0xFF
+#define R_PCH_XHCI_NXT_PTR1 0x71
+#define B_PCH_XHCI_NXT_PTR1 0xFF
+#define R_PCH_XHCI_PWR_CAP 0x72
+#define B_PCH_XHCI_PWR_CAP_PME_SUP 0xF800
+#define B_PCH_XHCI_PWR_CAP_D2_SUP BIT10
+#define B_PCH_XHCI_PWR_CAP_D1_SUP BIT9
+#define B_PCH_XHCI_PWR_CAP_AUX_CUR (BIT8 | BIT7 | BIT6)
+#define B_PCH_XHCI_PWR_CAP_DSI BIT5
+#define B_PCH_XHCI_PWR_CAP_PME_CLK BIT3
+#define B_PCH_XHCI_PWR_CAP_VER (BIT2 | BIT1 | BIT0)
+#define R_PCH_XHCI_PWR_CNTL_STS 0x74
+#define B_PCH_XHCI_PWR_CNTL_STS_PME_STS BIT15
+#define B_PCH_XHCI_PWR_CNTL_STS_DATASCL (BIT14 | BIT13)
+#define B_PCH_XHCI_PWR_CNTL_STS_DATASEL (BIT12 | BIT11 | BIT10 | BIT9)
+#define B_PCH_XHCI_PWR_CNTL_STS_PME_EN BIT8
+#define B_PCH_XHCI_PWR_CNTL_STS_PWR_STS (BIT1 | BIT0)
+#define V_PCH_XHCI_PWR_CNTL_STS_PWR_STS_D3 (BIT1 | BIT0)
+#define R_PCH_XHCI_MSI_MCTL 0x82
+#define R_PCH_XHCI_HSCFG2 0xA4
+#define R_PCH_XHCI_SSCFG1 0xA8
+#define R_PCH_XHCI_HSCFG1 0xAC
+#define R_PCH_XHCI_U2OCM 0xB0
+#define R_PCH_XHCI_U3OCM 0xD0
+#define V_PCH_XHCI_NUMBER_OF_OC_PINS 8
+
+#define R_PCH_XHCI_FUS 0xE0
+#define B_PCH_XHCI_FUS_USBR (BIT5)
+#define V_PCH_XHCI_FUS_USBR_EN 0
+#define V_PCH_XHCI_FUS_USBR_DIS (BIT5)
+
+#define R_PCH_XHCI_FC 0xFC
+
+#define B_PCH_XHCI_FUS_SSPRTCNT (BIT4 | BIT3)
+#define V_PCH_XHCI_FUS_SSPRTCNT_00B 0
+#define V_PCH_XHCI_FUS_SSPRTCNT_01B (BIT3)
+#define V_PCH_XHCI_FUS_SSPRTCNT_10B (BIT4)
+#define V_PCH_XHCI_FUS_SSPRTCNT_11B (BIT4 | BIT3)
+
+#define B_PCH_XHCI_FUS_HSPRTCNT (BIT2 | BIT1)
+#define V_PCH_XHCI_FUS_HSPRTCNT_00B 0
+#define V_PCH_XHCI_FUS_HSPRTCNT_01B (BIT1)
+#define V_PCH_XHCI_FUS_HSPRTCNT_10B (BIT2)
+#define V_PCH_XHCI_FUS_HSPRTCNT_11B (BIT2 | BIT1)
+
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_00B_CNT 6
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_01B_CNT 4
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_10B_CNT 2
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_11B_CNT 0
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_00B_MASK 0x3F
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_01B_MASK 0x0F
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_10B_MASK 0x03
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_11B_MASK 0x00
+
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_00B_CNT 14
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_01B_CNT 12
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_10B_CNT 10
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_11B_CNT 8
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_00B_MASK 0x3FFF
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_01B_MASK 0x3F3F
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_10B_MASK 0x03FF
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_11B_MASK 0x00FF
+
+#define V_PCH_LP_XHCI_FIXED_SSPRTCNT 4
+#define V_PCH_LP_XHCI_FIXED_SSPRTCNT_MASK 0x0F
+
+#define V_PCH_LP_XHCI_FIXED_HSPRTCNT 8
+#define V_PCH_LP_XHCI_FIXED_HSPRTCNT_MASK 0x00FF
+
+//
+// xHCI MMIO registers
+//
+
+//
+// 0x00 - 0x1F - Capability Registers
+//
+#define R_PCH_XHCI_CAPLENGTH 0x00
+#define R_PCH_XHCI_HCIVERSION 0x02
+#define R_PCH_XHCI_HCSPARAMS1 0x04
+#define R_PCH_XHCI_HCSPARAMS2 0x08
+#define R_PCH_XHCI_HCSPARAMS3 0x0C
+#define B_PCH_XHCI_HCSPARAMS3_U2DEL 0xFFFF0000
+#define B_PCH_XHCI_HCSPARAMS3_U1DEL 0x0000FFFF
+#define R_PCH_XHCI_HCCPARAMS 0x10
+#define B_PCH_XHCI_HCCPARAMS_LHRC BIT5
+#define B_PCH_XHCI_HCCPARAMS_MAXPSASIZE 0xF000
+#define R_PCH_XHCI_DBOFF 0x14
+#define R_PCH_XHCI_RTSOFF 0x18
+
+//
+// 0x80 - 0xBF - Operational Registers
+//
+#define R_PCH_XHCI_USBCMD 0x80
+#define B_PCH_XHCI_USBCMD_RS BIT0 ///< Run/Stop
+#define B_PCH_XHCI_USBCMD_RST BIT1 ///< HCRST
+#define R_PCH_XHCI_USBSTS 0x84
+#define B_PCH_XHCI_USBSTS_HCH BIT0
+#define B_PCH_XHCI_USBSTS_CNR BIT11
+
+//
+// 0x480 - 0x5CF - Port Status and Control Registers
+//
+#define R_PCH_LP_XHCI_PORTSC01USB2 0x480
+#define R_PCH_LP_XHCI_PORTSC02USB2 0x490
+#define R_PCH_LP_XHCI_PORTSC03USB2 0x4A0
+#define R_PCH_LP_XHCI_PORTSC04USB2 0x4B0
+#define R_PCH_LP_XHCI_PORTSC05USB2 0x4C0
+#define R_PCH_LP_XHCI_PORTSC06USB2 0x4D0
+#define R_PCH_LP_XHCI_PORTSC07USB2 0x4E0
+#define R_PCH_LP_XHCI_PORTSC08USB2 0x4F0
+#define R_PCH_LP_XHCI_PORTSC09USB2 0x500
+#define R_PCH_LP_XHCI_PORTSC10USB2 0x510
+
+#define R_PCH_LP_XHCI_PORTSC11USBR 0x520
+#define R_PCH_LP_XHCI_PORTSC12USBR 0x530
+
+#define R_PCH_LP_XHCI_PORTSC01USB3 0x540
+#define R_PCH_LP_XHCI_PORTSC02USB3 0x550
+#define R_PCH_LP_XHCI_PORTSC03USB3 0x560
+#define R_PCH_LP_XHCI_PORTSC04USB3 0x570
+#define R_PCH_LP_XHCI_PORTSC05USB3 0x580
+#define R_PCH_LP_XHCI_PORTSC06USB3 0x590
+
+//
+// 0x480 - 0x5CF - Port Status and Control Registers
+//
+#define R_PCH_H_XHCI_PORTSC01USB2 0x480
+#define R_PCH_H_XHCI_PORTSC02USB2 0x490
+#define R_PCH_H_XHCI_PORTSC03USB2 0x4A0
+#define R_PCH_H_XHCI_PORTSC04USB2 0x4B0
+#define R_PCH_H_XHCI_PORTSC05USB2 0x4C0
+#define R_PCH_H_XHCI_PORTSC06USB2 0x4D0
+#define R_PCH_H_XHCI_PORTSC07USB2 0x4E0
+#define R_PCH_H_XHCI_PORTSC08USB2 0x4F0
+#define R_PCH_H_XHCI_PORTSC09USB2 0x500
+#define R_PCH_H_XHCI_PORTSC10USB2 0x510
+#define R_PCH_H_XHCI_PORTSC11USB2 0x520
+#define R_PCH_H_XHCI_PORTSC12USB2 0x530
+#define R_PCH_H_XHCI_PORTSC13USB2 0x540
+#define R_PCH_H_XHCI_PORTSC14USB2 0x550
+
+#define R_PCH_H_XHCI_PORTSC15USBR 0x560
+#define R_PCH_H_XHCI_PORTSC16USBR 0x570
+
+#define R_PCH_H_XHCI_PORTSC01USB3 0x580
+#define R_PCH_H_XHCI_PORTSC02USB3 0x590
+#define R_PCH_H_XHCI_PORTSC03USB3 0x5A0
+#define R_PCH_H_XHCI_PORTSC04USB3 0x5B0
+#define R_PCH_H_XHCI_PORTSC05USB3 0x5C0
+#define R_PCH_H_XHCI_PORTSC06USB3 0x5D0
+#define R_PCH_H_XHCI_PORTSC07USB3 0x5E0
+#define R_PCH_H_XHCI_PORTSC08USB3 0x5F0
+#define R_PCH_H_XHCI_PORTSC09USB3 0x600
+#define R_PCH_H_XHCI_PORTSC10USB3 0x610
+
+#define B_PCH_XHCI_PORTSCXUSB2_WPR BIT31 ///< Warm Port Reset
+#define B_PCH_XHCI_PORTSCXUSB2_CEC BIT23 ///< Port Config Error Change
+#define B_PCH_XHCI_PORTSCXUSB2_PLC BIT22 ///< Port Link State Change
+#define B_PCH_XHCI_PORTSCXUSB2_PRC BIT21 ///< Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB2_OCC BIT20 ///< Over-current Change
+#define B_PCH_XHCI_PORTSCXUSB2_WRC BIT19 ///< Warm Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB2_PEC BIT18 ///< Port Enabled Disabled Change
+#define B_PCH_XHCI_PORTSCXUSB2_CSC BIT17 ///< Connect Status Change
+#define B_PCH_XHCI_PORTSCXUSB2_LWS BIT16 ///< Port Link State Write Strobe
+#define B_PCH_XHCI_USB2_U3_EXIT (BIT5 | BIT6 | BIT7 | BIT8)
+#define B_PCH_XHCI_USB2_U0_MASK (BIT5 | BIT6 | BIT7 | BIT8)
+#define B_PCH_XHCI_PORTSCXUSB2_PP BIT9
+#define B_PCH_XHCI_PORTSCXUSB2_PLS (BIT5 | BIT6 | BIT7 | BIT8) ///< Port Link State
+#define B_PCH_XHCI_PORTSCXUSB2_PR BIT4 ///< Port Reset
+#define B_PCH_XHCI_PORTSCXUSB2_PED BIT1 ///< Port Enable/Disabled
+#define B_PCH_XHCI_PORTSCXUSB2_CCS BIT0 ///< Current Connect Status
+#define B_PCH_XHCI_PORT_CHANGE_ENABLE_MASK (B_PCH_XHCI_PORTSCXUSB2_CEC | B_PCH_XHCI_PORTSCXUSB2_PLC | B_PCH_XHCI_PORTSCXUSB2_PRC | B_PCH_XHCI_PORTSCXUSB2_OCC | B_PCH_XHCI_PORTSCXUSB2_WRC | B_PCH_XHCI_PORTSCXUSB2_PEC | B_PCH_XHCI_PORTSCXUSB2_CSC | B_PCH_XHCI_PORTSCXUSB2_PED)
+#define B_PCH_XHCI_PORTPMSCXUSB2_PTC (BIT28 | BIT29 | BIT30 | BIT31) ///< Port Test Control
+
+#define B_PCH_XHCI_PORTSCXUSB3_WPR BIT31 ///< Warm Port Reset
+#define B_PCH_XHCI_PORTSCXUSB3_CEC BIT23 ///< Port Config Error Change
+#define B_PCH_XHCI_PORTSCXUSB3_PLC BIT22 ///< Port Link State Change
+#define B_PCH_XHCI_PORTSCXUSB3_PRC BIT21 ///< Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB3_OCC BIT20 ///< Over-current Change
+#define B_PCH_XHCI_PORTSCXUSB3_WRC BIT19 ///< Warm Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB3_PEC BIT18 ///< Port Enabled Disabled Change
+#define B_PCH_XHCI_PORTSCXUSB3_CSC BIT17 ///< Connect Status Change
+#define B_PCH_XHCI_PORTSCXUSB3_LWS BIT16 ///< Port Link State Write Strobe
+#define B_PCH_XHCI_PORTSCXUSB3_PP BIT9 ///< Port Power
+#define B_PCH_XHCI_PORTSCXUSB3_PLS (BIT8 | BIT7 | BIT6 | BIT5) ///< Port Link State
+#define V_PCH_XHCI_PORTSCXUSB3_PLS_POLLING 0x000000E0 ///< Link is in the Polling State
+#define V_PCH_XHCI_PORTSCXUSB3_PLS_RXDETECT 0x000000A0 ///< Link is in the RxDetect State
+#define V_PCH_XHCI_PORTSCXUSB3_PLS_DISABLED 0x00000080 ///< Link is in the RxDetect State
+#define B_PCH_XHCI_PORTSCXUSB3_PR BIT4 ///< Port Reset
+#define B_PCH_XHCI_PORTSCXUSB3_PED BIT1 ///< Port Enable/Disabled
+#define B_PCH_XHCI_PORTSCXUSB3_CHANGE_ENABLE_MASK (B_PCH_XHCI_PORTSCXUSB3_CEC | B_PCH_XHCI_PORTSCXUSB3_PLC | B_PCH_XHCI_PORTSCXUSB3_PRC | B_PCH_XHCI_PORTSCXUSB3_OCC | B_PCH_XHCI_PORTSCXUSB3_WRC | B_PCH_XHCI_PORTSCXUSB3_PEC | B_PCH_XHCI_PORTSCXUSB3_CSC | B_PCH_XHCI_PORTSCXUSB3_PED)
+//
+// 0x2000 - 0x21FF - Runtime Registers
+// 0x3000 - 0x307F - Doorbell Registers
+//
+#define R_PCH_XHCI_XECP_SUPP_USB2_2 0x8008
+#define R_PCH_XHCI_XECP_SUPP_USB3_2 0x8028
+#define R_PCH_XHCI_HOST_CTRL_SCH_REG 0x8094
+#define R_PCH_XHCI_HOST_CTRL_IDMA_REG 0x809C
+#define R_PCH_XHCI_PMCTRL 0x80A4
+#define R_PCH_XHCI_PGCBCTRL 0x80A8 ///< PGCB Control
+#define R_PCH_XHCI_HOST_CTRL_MISC_REG 0x80B0 ///< Host Controller Misc Reg
+#define R_PCH_XHCI_HOST_CTRL_MISC_REG_2 0x80B4 ///< Host Controller Misc Reg 2
+#define R_PCH_XHCI_SSPE 0x80B8 ///< Super Speed Port Enables
+#define B_PCH_XHCI_LP_SSPE_MASK 0x3F ///< LP: Mask for 6 USB3 ports
+#define B_PCH_XHCI_H_SSPE_MASK 0x3FF ///< H: Mask for 10 USB3 ports
+#define R_PCH_XHCI_AUX_CTRL_REG 0x80C0 ///< AUX_CTRL_REG - AUX Reset Control
+#define R_PCH_XHCI_DUAL_ROLE_CFG0 0x80D8
+#define R_PCH_XHCI_DUAL_ROLE_CFG1 0x80DC
+#define R_PCH_XHCI_AUX_CTRL_REG1 0x80E0
+#define R_PCH_XHCI_HOST_CTRL_PORT_LINK_REG 0x80EC ///< SuperSpeed Port Link Control
+#define R_PCH_XHCI_XECP_CMDM_CTRL_REG1 0x818C ///< Command Manager Control 1
+#define R_PCH_XHCI_XECP_CMDM_CTRL_REG2 0x8190 ///< Command Manager Control 2
+#define R_PCH_XHCI_XECP_CMDM_CTRL_REG3 0x8194 ///< Command Manager Control 3
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW1 0x80F0 ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW2 0x80F4 ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW3 0x80F8 ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW4 0x80FC ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_HOST_CTRL_TRM_REG2 0x8110 ///< HOST_CTRL_TRM_REG2 - Host Controller Transfer Manager Control 2
+#define R_PCH_XHCI_AUX_CTRL_REG2 0x8154 ///< AUX_CTRL_REG2 - Aux PM Control Register 2
+#define R_PCH_XHCI_AUXCLKCTL 0x816C ///< xHCI Aux Clock Control Register
+#define R_PCH_XHCI_HOST_IF_PWR_CTRL_REG0 0x8140 ///< HOST_IF_PWR_CTRL_REG0 - Power Scheduler Control 0
+#define R_PCH_XHCI_HOST_IF_PWR_CTRL_REG1 0x8144 ///< HOST_IF_PWR_CTRL_REG1 - Power Scheduler Control 1
+#define R_PCH_XHCI_XHCLTVCTL2 0x8174 ///< xHC Latency Tolerance Parameters - LTV Control
+#define R_PCH_XHCI_LTVHIT 0x817C ///< xHC Latency Tolerance Parameters - High Idle Time Control
+#define R_PCH_XHCI_LTVMIT 0x8180 ///< xHC Latency Tolerance Parameters - Medium Idle Time Control
+#define R_PCH_XHCI_LTVLIT 0x8184 ///< xHC Latency Tolerance Parameters - Low Idle Time Control
+#define R_PCH_XHCI_USB2PHYPM 0x8164 ///< USB2 PHY Power Management Control
+#define R_PCH_XHCI_PDDIS 0x8198 ///< xHC Pulldown Disable Control
+#define R_PCH_XHCI_THROTT 0x819C ///< XHCI Throttle Control
+#define R_PCH_XHCI_LFPSPM 0x81A0 ///< LFPS PM Control
+#define R_PCH_XHCI_THROTT2 0x81B4 ///< XHCI Throttle
+#define R_PCH_XHCI_LFPSONCOUNT 0x81B8 ///< LFPS On Count
+#define R_PCH_XHCI_D0I2CTRL 0x81BC ///< D0I2 Control Register
+#define R_PCH_XHCI_USB2PMCTRL 0x81C4 ///< USB2 Power Management Control
+
+//
+// SKL PCH LP FUSE
+//
+#define R_PCH_XHCI_LP_FUSE1 0x8410
+#define B_PCH_XHCI_LP_FUS_HSPRTCNT (BIT1)
+#define B_PCH_XHCI_LP_FUS_USBR (BIT5)
+#define R_PCH_XHCI_STRAP2 0x8420 ///< USB3 Mode Strap
+#define B_PCH_XHCI_STRAP2_USB3_SSIC_MODE (BIT1 | BIT0) ///< USB3/SSIC Mode
+#define R_PCH_XHCI_USBLEGCTLSTS 0x8470 ///< USB Legacy Support Control Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIBAR BIT31 ///< SMI on BAR Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIPCIC BIT30 ///< SMI on PCI Command Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIOSC BIT29 ///< SMI on OS Ownership Change Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIBARE BIT15 ///< SMI on BAR Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIPCICE BIT14 ///< SMI on PCI Command Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIOSOE BIT13 ///< SMI on OS Ownership Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIHSEE BIT4 ///< SMI on Host System Error Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_USBSMIE BIT0 ///< USB SMI Enable
+
+//
+// Extended Capability Registers
+//
+#define R_PCH_XHCI_USB2PDO 0x84F8
+#define B_PCH_XHCI_LP_USB2PDO_MASK 0x3FF ///< LP: Mask for 10 USB2 ports
+#define B_PCH_XHCI_H_USB2PDO_MASK 0x7FFF ///< H: Mask for 14 USB2 ports
+#define B_PCH_XHCI_USB2PDO_DIS_PORT0 BIT0
+
+#define R_PCH_XHCI_USB3PDO 0x84FC
+#define B_PCH_XHCI_LP_USB3PDO_MASK 0x3F ///< LP: Mask for 6 USB3 ports
+#define B_PCH_XHCI_H_USB3PDO_MASK 0x3FF ///< H: Mask for 10 USB3 ports
+#define B_PCH_XHCI_USB3PDO_DIS_PORT0 BIT0
+
+//
+// Debug Capability Descriptor Parameters
+//
+#define R_PCH_XHCI_DBC_DBCCTL 0x8760 ///< DBCCTL - DbC Control
+
+//
+// xDCI (OTG) USB Device Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_XDCI 20
+#define PCI_FUNCTION_NUMBER_PCH_XDCI 1
+
+//
+// xDCI (OTG) PCI Config Space Registers
+//
+#define R_PCH_XDCI_MEM_BASE 0x10
+#define V_PCH_XDCI_MEM_LENGTH 0x200000
+#define R_PCH_XDCI_PMCSR 0x84 ///< Power Management Control and Status Register
+#define R_PCH_XDCI_GENERAL_PURPOSER_REG1 0xA0 ///< General Purpose PCI RW Register1
+#define R_PCH_XDCI_CPGE 0xA2 ///< Chassis Power Gate Enable
+#define R_PCH_XDCI_GENERAL_PURPOSER_REG4 0xAC ///< General Purpose PCI RW Register4
+#define R_PCH_OTG_GENERAL_INPUT_REG 0xC0 ///< General Input Register
+
+//
+// xDCI (OTG) MMIO registers
+//
+#define R_PCH_XDCI_GCTL 0xC110 ///< Xdci Global Ctrl
+#define B_PCH_XDCI_GCTL_GHIBEREN BIT1 ///< Hibernation enable
+#define R_PCH_XDCI_GUSB2PHYCFG 0xC200 ///< Global USB2 PHY Configuration Register
+#define B_PCH_XDCI_GUSB2PHYCFG_SUSPHY BIT6 ///< Suspend USB2.0 HS/FS/LS PHY
+#define R_PCH_XDCI_GUSB3PIPECTL0 0xC2C0 ///< Global USB3 PIPE Control Register 0
+#define B_PCH_XDCI_GUSB3PIPECTL0_UX_IN_PX BIT27 ///< Ux Exit in Px
+#define R_PCH_XDCI_APBFC_U3PMU_CFG2 0x10F810
+#define R_PCH_XDCI_APBFC_U3PMU_CFG4 0x10F818
+#define R_PCH_XDCI_APBFC_U3PMU_CFG5 0x10F81C
+#define R_PCH_XDCI_APBFC_U3PMU_CFG6 0x10F820
+
+//
+// xDCI (OTG) Private Configuration Registers
+// (PID:OTG)
+//
+#define R_PCH_PCR_OTG_IOSF_A2 0xA2
+#define R_PCH_PCR_OTG_IOSF_PMCTL 0x1D0
+#define R_PCH_PCR_OTG_PCICFGCTRL1 0x200
+#define B_PCH_PCR_OTG_PCICFGCTRL_PCI_IRQ 0x0FF00000
+#define N_PCH_PCR_OTG_PCICFGCTRL_PCI_IRQ 20
+#define B_PCH_PCR_OTG_PCICFGCTRL_ACPI_IRQ 0x000FF000
+#define N_PCH_PCR_OTG_PCICFGCTRL_ACPI_IRQ 12
+#define B_PCH_PCR_OTG_PCICFGCTRL_INT_PIN 0x00000F00
+#define N_PCH_PCR_OTG_PCICFGCTRL_INT_PIN 8
+#define B_PCH_PCR_OTG_PCICFGCTRL_BAR1_DIS 0x00000080
+#define B_PCH_PCR_OTG_PCICFGCTRL_PME_SUP 0x0000007C
+#define B_PCH_PCR_OTG_PCICFGCTRL_ACPI_INT_EN 0x00000002
+#define B_PCH_PCR_OTG_PCICFGCTRL_PCI_CFG_DIS 0x00000001
+
+//
+// USB2 Private Configuration Registers
+// USB2 HIP design featured
+// (PID:USB2)
+//
+#define R_PCH_PCR_USB2_GLOBAL_PORT 0x4001 ///< USB2 GLOBAL PORT
+#define R_PCH_PCR_USB2_400C 0x400C
+#define R_PCH_PCR_USB2_PP_LANE_BASE_ADDR 0x4000 ///< PP LANE base address
+#define V_PCH_PCR_USB2_PER_PORT 0x00 ///< USB2 PER PORT Addr[7:2] = 0x00
+#define V_PCH_PCR_USB2_UTMI_MISC_PER_PORT 0x08 ///< UTMI MISC REG PER PORT Addr[7:2] = 0x08
+#define V_PCH_PCR_USB2_PER_PORT_2 0x26 ///< USB2 PER PORT 2 Addr[7:2] = 0x26
+#define R_PCH_PCR_USB2_402A 0x402A
+#define R_PCH_PCR_USB2_GLB_ADP_VBUS_REG 0x402B ///< GLB ADP VBUS REG
+#define R_PCH_PCR_USB2_GLOBAL_PORT_2 0x402C ///< USB2 GLOBAL PORT 2
+#define R_PCH_PCR_USB2_7034 0x7034
+#define R_PCH_PCR_USB2_7038 0x7038
+#define R_PCH_PCR_USB2_703C 0x703C
+#define R_PCH_PCR_USB2_7040 0x7040
+#define R_PCH_PCR_USB2_7044 0x7044
+#define R_PCH_PCR_USB2_7048 0x7048
+#define R_PCH_PCR_USB2_704C 0x704C
+#define R_PCH_PCR_USB2_CFG_COMPBG 0x7F04 ///< USB2 COMPBG
+
+//
+// xHCI SSIC registers
+//
+#define R_PCH_XHCI_SSIC_GLOBAL_CONF_CTRL 0x8804 ///< SSIC Global Configuration Control
+#define R_PCH_XHCI_SSIC_CONF_REG1_PORT_1 0x8808 ///< SSIC Configuration Register 1 Port 1
+#define R_PCH_XHCI_SSIC_CONF_REG2_PORT_1 0x880C ///< SSIC Configuration Register 2 Port 1
+#define R_PCH_XHCI_SSIC_CONF_REG3_PORT_1 0x8810 ///< SSIC Configuration Register 3 Port 1
+#define R_PCH_XHCI_SSIC_CONF_REG1_PORT_2 0x8838 ///< SSIC Configuration Register 1 Port 2
+#define R_PCH_XHCI_SSIC_CONF_REG2_PORT_2 0x883C ///< SSIC Configuration Register 2 Port 2
+#define R_PCH_XHCI_SSIC_CONF_REG3_PORT_2 0x8840 ///< SSIC Configuration Register 3 Port 2
+#define B_PCH_XHCI_SSIC_CONF_REG2_PORT_UNUSED BIT31
+#define B_PCH_XHCI_SSIC_CONF_REG2_PROG_DONE BIT30
+
+#define R_PCH_XHCI_SSIC_PROF_ATTR_PORT_1 0x8900 ///< Profile Attributes: Port 1 ... N
+#define R_PCH_XHCI_SSIC_ACCESS_CONT_PORT_1 0x8904 ///< SSIC Port N Register Access Control: Port 1
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_0C 0x890C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_10 0x8910
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_14 0x8914
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_18 0x8918
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_1C 0x891C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_20 0x8920
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_24 0x8924
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_28 0x8928
+
+#define R_PCH_XHCI_SSIC_PROF_ATTR_PORT_2 0x8A10 ///< Profile Attributes: Port 2 ... N
+#define R_PCH_XHCI_SSIC_ACCESS_CONT_PORT_2 0x8A14 ///< SSIC Port N Register Access Control: Port 2
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_0C 0x8A1C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_10 0x8A20
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_14 0x8A24
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_18 0x8A28
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_1C 0x8A2C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_20 0x8A30
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_24 0x8A34
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_28 0x8A38
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h
new file mode 100644
index 0000000000..5e7674a412
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h
@@ -0,0 +1,128 @@
+/** @file
+ Header file for DxePchHdaLib - NHLT structure definitions.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DXE_PCH_HDA_NHLT_H_
+#define _DXE_PCH_HDA_NHLT_H_
+
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI support protocol instance signature definition.
+//
+#define NHLT_ACPI_TABLE_SIGNATURE SIGNATURE_32 ('N', 'H', 'L', 'T')
+
+// MSFT defined structures
+#define SPEAKER_FRONT_LEFT 0x1
+#define SPEAKER_FRONT_RIGHT 0x2
+#define SPEAKER_FRONT_CENTER 0x4
+#define SPEAKER_BACK_LEFT 0x10
+#define SPEAKER_BACK_RIGHT 0x20
+
+#define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER)
+#define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
+#define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
+
+#define WAVE_FORMAT_EXTENSIBLE 0xFFFE /* Microsoft */
+#define KSDATAFORMAT_SUBTYPE_PCM \
+ {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}
+
+#pragma pack (push, 1)
+
+typedef struct {
+ UINT16 wFormatTag;
+ UINT16 nChannels;
+ UINT32 nSamplesPerSec;
+ UINT32 nAvgBytesPerSec;
+ UINT16 nBlockAlign;
+ UINT16 wBitsPerSample;
+ UINT16 cbSize;
+} WAVEFORMATEX;
+
+typedef struct {
+ WAVEFORMATEX Format;
+ union {
+ UINT16 wValidBitsPerSample;
+ UINT16 wSamplesPerBlock;
+ UINT16 wReserved;
+ } Samples;
+ UINT32 dwChannelMask;
+ GUID SubFormat;
+} WAVEFORMATEXTENSIBLE;
+
+//
+// List of supported link type.
+//
+enum NHLT_LINK_TYPE
+{
+ HdaNhltLinkHd = 0,
+ HdaNhltLinkDsp = 1,
+ HdaNhltLinkDmic = 2,
+ HdaNhltLinkSsp = 3,
+ HdaNhltLinkInvalid
+};
+
+//
+// List of supported device type.
+//
+enum NHLT_DEVICE_TYPE
+{
+ HdaNhltDeviceBt = 0,
+ HdaNhltDeviceDmic = 1,
+ HdaNhltDeviceI2s = 4,
+ HdaNhltDeviceInvalid
+};
+
+typedef struct {
+ UINT32 CapabilitiesSize;
+ UINT8 Capabilities[1];
+} SPECIFIC_CONFIG;
+
+typedef struct {
+ WAVEFORMATEXTENSIBLE Format;
+ SPECIFIC_CONFIG FormatConfiguration;
+} FORMAT_CONFIG;
+
+typedef struct {
+ UINT8 FormatsCount;
+ FORMAT_CONFIG FormatsConfiguration[1];
+} FORMATS_CONFIG;
+
+typedef struct {
+ UINT32 EndpointDescriptorLength;
+ UINT8 LinkType;
+ UINT8 InstanceId;
+ UINT16 HwVendorId;
+ UINT16 HwDeviceId;
+ UINT16 HwRevisionId;
+ UINT32 HwSubsystemId;
+ UINT8 DeviceType;
+ UINT8 Direction;
+ UINT8 VirtualBusId;
+ SPECIFIC_CONFIG EndpointConfig;
+ FORMATS_CONFIG FormatsConfig;
+} ENDPOINT_DESCRIPTOR;
+
+//
+// High Level Table structure
+//
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header; //{'N', 'H', 'L', 'T'}
+ UINT8 EndpointCount; // Actual number of endpoints
+ ENDPOINT_DESCRIPTOR EndpointDescriptors[1];
+ SPECIFIC_CONFIG OedConfiguration;
+} NHLT_ACPI_TABLE;
+
+#pragma pack (pop)
+
+#endif // _DXE_PCH_HDA_NHLT_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h
new file mode 100644
index 0000000000..f555182bc4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h
@@ -0,0 +1,212 @@
+/** @file
+ Header file for GpioPrivateLib.
+ All function in this library is available for PEI, DXE, and SMM,
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GPIO_PRIVATE_LIB_H_
+#define _GPIO_PRIVATE_LIB_H_
+
+#include <GpioConfig.h>
+
+/**
+ This procedure will get value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[out] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ OUT UINT32 *RegVal
+ );
+
+/**
+ This procedure will set value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[in] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ IN UINT32 RegVal
+ );
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI. Relation between Index and GpioPad number is:
+ Index = GpioGroup + 24 * GpioPad
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiSmiEnRegAddress Address of GPI SMI Enable register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiSmiEnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ );
+
+/**
+ This procedure will clear GPIO_UNLOCK_SMI_STS
+
+ @param[in] None
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearUnlockSmiSts (
+ VOID
+ );
+
+/**
+ This procedure will set GPIO Driver IRQ number
+
+ @param[in] Irq Irq number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid IRQ number
+**/
+EFI_STATUS
+GpioSetIrq (
+ IN UINT8 Irq
+ );
+
+/**
+ This procedure will perform special handling of GPP_A_12 on PCH-LP.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GpioA12SpecialHandling (
+ VOID
+ );
+
+/**
+ This function sets ISH I2C controller pins into native mode
+
+ @param[in] IshI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshI2cPinsIntoNativeMode (
+ IN UINT32 IshI2cControllerNumber
+ );
+
+/**
+ This function sets ISH UART controller pins into native mode
+
+ @param[in] IshUartControllerNumber UART controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshUartPinsIntoNativeMode (
+ IN UINT32 IshUartControllerNumber
+ );
+
+/**
+ This function sets ISH SPI controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshSpiPinsIntoNativeMode (
+ VOID
+ );
+
+/**
+ This function sets ISH GP pins into native mode
+
+ @param[in] IshGpPinNumber ISH GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshGpPinsIntoNativeMode (
+ IN UINT32 IshGpPinNumber
+ );
+
+/**
+ Returns pad for given CLKREQ# index.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return CLKREQ# pad.
+**/
+GPIO_PAD
+GpioGetClkreqPad (
+ IN UINT32 ClkreqIndex
+ );
+
+/**
+ Enables CLKREQ# pad in native mode.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return none
+**/
+VOID
+GpioEnableClkreq (
+ IN UINT32 ClkreqIndex
+ );
+
+/**
+ This function checks if GPIO pin for PCHHOTB is in NATIVE MODE
+
+ @param[in] none
+
+ @retval TRUE Pin is in PCHHOTB native mode
+ FALSE Pin is in gpio mode or is not owned by HOST
+**/
+BOOLEAN
+GpioIsPchHotbPinInNativeMode (
+ VOID
+ );
+
+/**
+ This function sets CPU GP pins into native mode
+
+ @param[in] CpuGpPinNum CPU GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCpuGpPinsIntoNativeMode (
+ IN UINT32 CpuGpPinNum
+ );
+
+#endif // _GPIO_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h
new file mode 100644
index 0000000000..8f0a1adf38
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h
@@ -0,0 +1,290 @@
+/** @file
+ Implement the I2C port control.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _I2C_MASTER_COMMON_LIB_H_
+#define _I2C_MASTER_COMMON_LIB_H_
+
+///
+/// Each I2C port instance uses an I2C_MASTER_CONTEXT structure
+/// to maintain its context.
+///
+typedef struct {
+ EFI_I2C_CONTROLLER_CAPABILITIES Capabilities;
+ //
+ // I2C master's mmio addresses cached to speed up operation
+ //
+ UINTN MmioAddress;
+ UINTN ConfigAddress;
+ //
+ // copy of all pointers and data provided in StartRequest call
+ // if transfer didn't finish in one go, those will be needed to continue it
+ //
+ EFI_I2C_REQUEST_PACKET *Request;
+ //
+ // Internal copy of Transfer status, to be returned from StartRequest()
+ //
+ EFI_STATUS TransferStatus;
+ //
+ // Index (Operation:Postition in Buffer) of next operation to be performed
+ // Write is for both R/W operations as both need to be put in fifo
+ // Read is for Read only, for filling buffer with data retrieved from bus
+ //
+ UINTN WriteOp;
+ UINTN WritePos;
+ UINTN ReadOp;
+ UINTN ReadPos;
+ BOOLEAN TransferInProgress;
+} I2C_MASTER_CONTEXT;
+
+/**
+ Prepare I2c controller for use: enable its mmio range, put in D0, get out of reset
+
+ @param[in] Context - driver context
+**/
+VOID
+PrepareController (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Determine the state of the I2C controller
+
+ @param[in] Context - driver context
+
+ @retval TRUE The I2C controller is active
+ @retval FALSE The I2C controller is idle
+**/
+BOOLEAN
+IsHardwareActive (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Updates WriteOperation and WritePosition, two variables that determine
+ which part of Request is being committed to I2C bus.
+ This iterates over both Read and Write operations from a request, because
+ things that need to be written to WriteFifo are both I2c bus writes
+ and I2c bus reads (the command to perform bus read needs to be put into Write Fifo)
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateWritePosition (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ FindReadOp checks if current Operation is of Read type. If so, returns.
+ If not, increases ReadOp until it finds one or goes beyond Request's OperationCount
+
+ @param[in] Context - driver context
+**/
+VOID
+FindReadOp (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Updates ReadOperation and ReadPosition, two variables that determine
+ which part of Request is being filled with data incoming from I2C reads.
+ This iterates only over Read operations from a request.
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateReadPosition (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ ValidateRequest checks if Request is valid and can be started
+
+ @param[in] Context driver context
+ @param[in] RequestPacket content of I2C request package
+
+ @retval EFI_SUCCESS Request is valid and can be started
+ @retval EFI_ALREADY_STARTED The controller is busy with another transfer
+ @retval EFI_BAD_BUFFER_SIZE Transfer size too big
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL, invalid Operation flags
+ @retval EFI_UNSUPPORTED 10bit I2C address or "ping" operation attempted (0-byte transfer, address byte not followed by any data)
+**/
+EFI_STATUS
+ValidateRequest (
+ I2C_MASTER_CONTEXT *Context,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ );
+
+/**
+ IsLastFromRequest checks if WritePos and WriteOp point to the last byte of the request
+
+ @param[in] Context - driver context
+**/
+BOOLEAN
+IsLastFromRequest (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ IsLastFromRequest checks if WritePos and WriteOp point to the first byte of an operation
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsFirstFromOperation (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ InitializeTransfer checks if HW is ready to accept new transfer.
+ If so, sets up slave address
+
+ @param[in] Context - driver context
+
+ @retval Status
+**/
+EFI_STATUS
+InitializeTransfer (
+ I2C_MASTER_CONTEXT *Context,
+ UINTN SlaveAddress,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ );
+
+/**
+ WriteFifo writes to I2c controller's transmit Fifo. Data written to Fifo could be
+ - data bytes to be written to an I2C slave
+ - read requests that trigger I2C bus reads
+ First transfer from each operation adds Restart bit which triggers Restart condition on bus
+ Last transfer from the whole Request adds Stop bit which triggers Stop condtion on bus
+ Driver keeps track of which parts of Request were already committed to hardware using
+ pointer consisting of WritePosition and WriteOperation variables. This pointer is updated
+ every time data byte/read request is committed to FIFO
+ WriteFifo executes while there's anything more to write and the write fifo isn't full
+
+ @param[in] Context - driver context
+**/
+VOID
+WriteFifo (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ ReadFifo reads from I2c controller's receive Fifo. It contains data retrieved
+ from slave device as a result of executing read transfers, which were
+ triggered by putting read requests into Write Fifo. Retrieved data is copied into buffers
+ pointed to by Request structure.
+ Driver keeps track where to copy incoming data using pointer consisting of
+ ReadPosition and ReadOperation variables. This pointer is updated
+ every time data was retrieved from hardware
+ ReadFifo executes while there's data available and receive buffers were not filled
+
+ @param[in] Context - driver context
+**/
+VOID
+ReadFifo (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ CheckErrors checks if there were any transfer errors.
+
+ @param[in] Context - driver context
+**/
+VOID
+CheckErrors (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Transfer is finished when all requested operations were placed in fifo,
+ all read requests were filled and hardware is inactive
+ The last part is necessary for write-only transfers where after
+ placing all writes in fifo sw needs to wait until they flush down the bus
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsTransferFinished (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Clean up Hw activity and errors
+ Return status to Request's submitter and signal the event that tells
+ it that the request is complete
+ Clear up Sw context to allow new request to start
+
+ @param[in] Context - driver context
+**/
+VOID
+FinishTransfer (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ PerformTransfer. For synchronous transfer this function is called in a loop
+ and for asynchronous transfers, as a timer callback. It writes data and/or
+ read requests to hadrware, copies read data to destination buffers. When
+ transfer completes, it cleans up Sw context and Hw registers in preparation
+ for new transfer
+
+ @param[in] Context - driver context
+**/
+VOID
+PerformTransfer (
+ IN I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Set the I2C controller bus clock frequency.
+
+ This routine must be called at or below TPL_NOTIFY.
+
+ The software and controller do a best case effort of using the specified
+ frequency for the I2C bus. If the frequency does not match exactly then
+ the controller will use lower frequency for the I2C to avoid exceeding
+ the operating conditions for any of the I2C devices on the bus.
+ For example if 400 KHz was specified and the controller's divide network
+ only supports 402 KHz or 398 KHz then the controller would be set to 398
+ KHz.
+
+ @param[in] MmioAddress Address of I2C controller
+ @param[in] BusClockHertz New I2C bus clock frequency in Hertz
+
+ @retval EFI_SUCCESS The bus frequency was set successfully.
+ @retval EFI_UNSUPPORTED The controller does not support this frequency.
+**/
+
+EFI_STATUS
+FrequencySet (
+ IN UINTN MmioAddress,
+ IN OUT UINTN *BusClockHertz
+ );
+
+/**
+ Reset the I2C controller
+
+ @param[in] MmioAddress Address of I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+I2cReset (
+ IN UINTN MmioAddress
+ );
+
+#endif // _I2C_MASTER_COMMON_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h
new file mode 100644
index 0000000000..f3f7c27340
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h
@@ -0,0 +1,62 @@
+/** @file
+ This library provides PCH HD Audio functions.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_HDA_LIB_H_
+#define _PCH_HDA_LIB_H_
+
+#include <Library/DxePchHdaNhlt.h>
+#include <PchHdaEndpoints.h>
+
+/**
+ Prints NHLT (Non HDA-Link Table) to be exposed via ACPI (aka. OED (Offload Engine Driver) Configuration Table).
+
+ @param[in] *NhltAcpiTable The NHLT table to print
+**/
+VOID
+NhltAcpiTableDump(
+ IN NHLT_ACPI_TABLE *NhltTable
+ );
+
+/**
+ Constructs EFI_ACPI_DESCRIPTION_HEADER structure for NHLT table.
+
+ @param[in][out] *NhltTable NHLT table for which header will be created
+ @param[in] NhltTableSize Size of NHLT table
+
+ @retval None
+**/
+VOID
+NhltAcpiHeaderConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN UINT32 NhltTableSize
+ );
+
+/**
+ Constructs NHLT_ACPI_TABLE structure based on given Endpoints list.
+
+ @param[in] *EndpointTable List of endpoints for NHLT
+ @param[in][out] **NhltTable NHLT table to be created
+ @param[in][out] *NhltTableSize Size of created NHLT table
+
+ @retval EFI_SUCCESS NHLT created successfully
+ @retval EFI_BAD_BUFFER_SIZE Not enough resources to allocate NHLT
+**/
+EFI_STATUS
+NhltConstructor(
+ IN PCH_HDA_NHLT_ENDPOINTS *EndpointTable,
+ IN OUT NHLT_ACPI_TABLE **NhltTable,
+ IN OUT UINT32 *NhltTableSize
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h
new file mode 100644
index 0000000000..8c016c624f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h
@@ -0,0 +1,191 @@
+/** @file
+ Header file for PCH Init Common Lib
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_INIT_COMMON_LIB_H_
+#define _PCH_INIT_COMMON_LIB_H_
+
+#include <PchPolicyCommon.h>
+#include <PchAccess.h>
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ );
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpPort Root Port Number
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpPort
+ );
+
+/**
+ Calculate root port device number based on physical port index.
+
+ @param[in] RpIndex Root port index (0-based).
+
+ @retval Root port device number.
+**/
+UINT32
+PchGetPcieRpDevice (
+ IN UINT32 RpIndex
+ );
+
+/**
+ This function reads Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[out] *Data32 Value of Config register
+
+ @retval EFI_SUCCESS SBI Read successful.
+**/
+EFI_STATUS
+PchSbiRpPciRead32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ OUT UINT32 *Data32
+ );
+
+/**
+ This function And then Or Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[in] Data32And Value of Config register to be And-ed
+ @param[in] Data32AOr Value of Config register to be Or-ed
+
+ @retval EFI_SUCCESS SBI Read and Write successful.
+**/
+EFI_STATUS
+PchSbiRpPciAndThenOr32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ IN UINT32 Data32And,
+ IN UINT32 Data32Or
+ );
+
+/**
+ Configure root port function number mapping
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+PchConfigureRpfnMapping (
+ VOID
+ );
+
+/**
+ This function lock down the P2sb SBI before going into OS.
+
+ @param[in] SbiUnlock
+**/
+VOID
+ConfigureP2sbSbiLock (
+ IN CONST BOOLEAN SbiUnlock
+ );
+
+/**
+ Bios will remove the host accessing right to Sideband register range
+ prior to any 3rd party code execution.
+
+ 1) Set EPMASK5 Offset C4 (bits 29, 28, 27, 26, 17, 16, 10, 1) to disable Sideband access for PSF and MIPI controller
+ 2) Set EPMASK7 Offset CC (bits 6, 5) to disable Sideband access for XHCI controller
+ 3) Set the "Endpoint Mask Lock!", P2SB PCI offset E2h bit[1] to 1.
+**/
+VOID
+RemoveSidebandAccess(
+ VOID
+ );
+
+/**
+ Configure PMC static function disable lock
+**/
+VOID
+ConfigurePmcStaticFunctionDisableLock (
+ VOID
+ );
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+PrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ );
+
+VOID
+PrintPchPciConfigSpace (
+ VOID
+ );
+
+/**
+ Check if RST PCIe Storage Remapping is enabled based on policy
+
+ @param[in] RstPcieStorageRemap The PCH PCIe Storage remapping
+
+ @retval TRUE RST PCIe Storage Remapping is enabled
+ @retval FALSE RST PCIe Storage Remapping is disabled
+**/
+BOOLEAN
+IsRstPcieStorageRemapEnabled (
+ IN CONST PCH_RST_PCIE_STORAGE_CONFIG *RstPcieStorageRemap
+ );
+
+/**
+ Disable the RST remap address decoding range while RST is disabled.
+
+ @param[in] AhciBar ABAR address
+**/
+VOID
+DisableRstRemapDecoding (
+ UINT32 AhciBar
+ );
+
+/**
+ Program Xhci Port Disable Override
+
+ @param[in] XhciMmioBase xHCI controller MBAR0 address
+ @param[in] Usb2DisabledPorts Disabled USB2 ports where each port has its disabling bit
+ @param[in] Usb3DisabledPorts Disabled USB3 ports where each port has its disabling bit
+
+ @retval TRUE if platform reset is needed, otherwise FALSE is returned
+**/
+BOOLEAN
+UsbPdoProgramming (
+ IN UINTN XhciMmioBase,
+ IN UINT32 Usb2DisabledPorts,
+ IN UINT32 Usb3DisabledPorts
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h
new file mode 100644
index 0000000000..49c89a2fcc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h
@@ -0,0 +1,284 @@
+/** @file
+ Header file for PCH PCI Express helpers library
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PCI_EXPRESS_HELPERS_LIB_H_
+#define _PCH_PCI_EXPRESS_HELPERS_LIB_H_
+
+#include <PchPolicyCommon.h>
+
+typedef enum {
+ TpoScale2us,
+ TpoScale10us,
+ TpoScale100us,
+ TpoScaleMax
+} T_PO_SCALE;
+
+typedef struct {
+ UINT32 Value;
+ T_PO_SCALE Scale;
+} T_POWER_ON;
+//
+// Function prototypes
+//
+T_POWER_ON GetTpoCapability (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ );
+
+T_POWER_ON GetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ );
+
+/*
+ Sets Tpower_on in a device
+
+ According to spec, Tpower_on can only be updated while L1_2 is disabled
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+ @param[in] Tpo value to be programmed into Tpower_on
+*/
+VOID SetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset,
+ T_POWER_ON Tpo
+ );
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+*/
+UINT32 TpoToUs (
+ T_POWER_ON Tpo
+ );
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ );
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Rreporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ );
+
+/**
+ This returns ClkReq Number from Port Number
+
+ @param[in] PortIndex PCIe Port Number (Zero Base. Please use 23 for GBe)
+
+ @retval ClkReq Number
+**/
+UINT8
+GetPortClkReqNumber (
+ IN UINT8 PortIndex
+ );
+
+/**
+ Set Common clock to Root port and Endpoint PCI device
+
+ @param[in] Bus1 Root port Pci Bus Number
+ @param[in] Device1 Root port Pci Device Number
+ @param[in] Function1 Root port Pci Function Number
+ @param[in] Bus2 Endpoint Pci Bus Number
+ @param[in] Device2 Endpoint Pci Device Number
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS VC mapping correctly initialized
+**/
+EFI_STATUS
+PcieSetCommonClock (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2
+ );
+
+/**
+ This function enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] RootDevice Rootport Device Number
+ @param[in] RootFunction Rootport Function Number
+
+ @retval None
+**/
+VOID
+PcieSetClkreq (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction
+ );
+
+/**
+ This function get or set the Max Payload Size on all the end point functions
+
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+ @param[in] MaxPayload The Max Payolad Size of the root port
+ @param[in] Operation True: Set the Max Payload Size on all the end point functions
+ False: Get the Max Payload Size on all the end point functions
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieMaxPayloadSize (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN Operation
+ );
+
+/**
+ This function disable the forwarding of EOI messages unless it discovers
+ an IOAPIC behind this root port.
+
+ @param[in] RootBus The Bus Number of the root port
+ @param[in] RootDevice The Device Number of the root port
+ @param[in] RootFunction The Function Number of the root port
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieSetEoiFwdDisable (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice
+ );
+
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitRootPortDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN BOOLEAN EnableCpm
+ );
+
+/**
+ Get current PCIe link speed.
+
+ @param[in] RpBase Root Port base address
+ @return Link speed
+**/
+UINT32
+GetLinkSpeed (
+ UINTN RpBase
+ );
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port base address
+ @return Max link speed
+**/
+UINT32
+GetMaxLinkSpeed (
+ UINTN RpBase
+ );
+
+/**
+ Get Pch Maximum Pcie Controller Number
+
+ @retval Pch Maximum Pcie Controller Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPcieControllerNum (
+ VOID
+ );
+
+/**
+ PCIe controller configuration.
+**/
+typedef enum {
+ Pcie4x1 = 0,
+ Pcie1x2_2x1 = 1,
+ Pcie2x2 = 2,
+ Pcie1x4 = 3
+} PCIE_CONTROLLER_CONFIG;
+
+/**
+ Returns the PCIe controller configuration (4x1, 1x2-2x1, 2x2, 1x4)
+
+ @param[in] ControllerIndex Number of PCIe controller (0 based)
+
+ @retval PCIe controller configuration
+**/
+PCIE_CONTROLLER_CONFIG
+GetPcieControllerConfig (
+ IN UINT32 ControllerIndex
+ );
+#endif // _PEI_DXE_SMM_PCH_PCI_EXPRESS_HELPERS_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h
new file mode 100644
index 0000000000..ad390103ce
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h
@@ -0,0 +1,401 @@
+/** @file
+ Header file for PchPsfPrivateLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PSF_PRIVATE_LIB_H_
+#define _PCH_PSF_PRIVATE_LIB_H_
+
+/**
+ Hide CIO2 devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideCio2Device (
+ VOID
+ );
+
+/**
+ Disable CIO2 device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableCio2Device (
+ VOID
+ );
+
+/**
+ Disable HDAudio device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableHdaDevice (
+ VOID
+ );
+
+/**
+ Disable xDCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXdciDevice (
+ VOID
+ );
+
+/**
+ Disable xHCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXhciDevice (
+ VOID
+ );
+
+/**
+ Disable SATA device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSataDevice (
+ VOID
+ );
+
+typedef enum {
+ PchPsfEmmc = 0,
+ PchPsfSdio,
+ PchPsfSdcard,
+ PchPsfUfs,
+ PchPsfMaxScsDevNum
+} PCH_PSF_SCS_DEV_NUM;
+
+/**
+ Disable SCS device at PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsDevice (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ );
+
+/**
+ Disable SCS devices BAR1 PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsBar1 (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ );
+
+/**
+ Disable ISH device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshDevice (
+ VOID
+ );
+
+/**
+ Disable ISH BAR1 at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshBar1 (
+ VOID
+ );
+
+/**
+ Disable GbE device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableGbeDevice (
+ VOID
+ );
+
+/**
+ Disable SMBUS device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSmbusDevice (
+ VOID
+ );
+
+/**
+ Disable Thermal device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableThermalDevice (
+ VOID
+ );
+
+/**
+ Hide Thermal device PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideThermalDevice (
+ VOID
+ );
+
+/**
+ Hide TraceHub ACPI devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubAcpiDevice (
+ VOID
+ );
+
+/**
+ This procedure will hide TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubDevice (
+ VOID
+ );
+
+/**
+ This procedure will reveal TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfRevealTraceHubDevice (
+ VOID
+ );
+
+/**
+ This procedure will disable TraceHub device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableTraceHubDevice (
+ VOID
+ );
+
+/**
+ Re-enable PCIe Root Port at PSF level after it was disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRootPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Disable PCIe Root Port at PSF level
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Disable PCIe Root Port at PSF level.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPortWithS3BootScript (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Program PSF grant counts for PCI express depending on controllers configuration
+
+ @param[in] Controller PCIe controller index
+ @param[in] ControllerConfig Port configuration of controller
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurePcieGrantCounts (
+ UINT8 Controller,
+ UINT8 ControllerConfig
+ );
+
+/**
+ Disable ISM NP Completion Tracking for GbE PSF port
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIsmNpCompletionTrackForGbe (
+ VOID
+ );
+
+/**
+ Program PSF EOI Multicast configuration
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfSetEoiMulticastConfiguration (
+ VOID
+ );
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Reload default RP PSF device number and function number.
+ The PSF register doesn't got reset after system reset, which will result in mismatch between
+ PSF register setting and PCIE PCR PCD register setting. Reset PSF register in early phase
+ to avoid cycle decoding confusing.
+
+ @param[in] None
+
+ @retval Status
+**/
+VOID
+PsfReloadDefaultPcieRpDevFunc (
+ VOID
+ );
+
+/**
+ Assign new function number for PCIe Port Number.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+ @param[in] NewFunction New Function number
+
+ @retval None
+**/
+VOID
+PsfSetPcieFunctionWithS3BootScript (
+ IN UINT32 RpIndex,
+ IN UINT32 NewFunction
+ );
+
+/**
+ This function enables PCIe Relaxed Order in PSF
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRelaxedOrder (
+ VOID
+ );
+
+/**
+ Configure PSF power management.
+ Must be called after all PSF configuration is completed.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfConfigurePowerManagement (
+ VOID
+ );
+
+/**
+ Enable VTd support in PSF.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchPsfEnableVtd (
+ VOID
+ );
+
+/**
+ Disable PSF address-based peer-to-peer decoding.
+**/
+VOID
+PchPsfDisableP2pDecoding (
+ VOID
+ );
+
+
+#endif // _PCH_PSF_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h
new file mode 100644
index 0000000000..5c2a6c30e2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h
@@ -0,0 +1,166 @@
+/** @file
+ PCH Smbus Protocol
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SMBUS_COMMON_LIB_H
+#define _PCH_SMBUS_COMMON_LIB_H
+
+//
+// Definitions
+//
+#define STALL_PERIOD 10 * STALL_ONE_MICRO_SECOND ///< 10 microseconds
+#define STALL_TIME STALL_ONE_SECOND ///< 1 second
+#define BUS_TRIES 3 ///< How many times to retry on Bus Errors
+#define SMBUS_NUM_RESERVED 38 ///< Number of device addresses that are reserved by the SMBus spec.
+#define SMBUS_ADDRESS_ARP 0xC2 >> 1
+#define SMBUS_DATA_PREPARE_TO_ARP 0x01
+#define SMBUS_DATA_RESET_DEVICE 0x02
+#define SMBUS_DATA_GET_UDID_GENERAL 0x03
+#define SMBUS_DATA_ASSIGN_ADDRESS 0x04
+#define SMBUS_GET_UDID_LENGTH 17 ///< 16 byte UDID + 1 byte address
+//
+// Private data and functions
+//
+
+typedef
+UINT8
+(EFIAPI *SMBUS_IO_READ) (
+ IN UINT8 Offset
+ );
+
+typedef
+VOID
+(EFIAPI *SMBUS_IO_WRITE) (
+ IN UINT8 Offset,
+ IN UINT8 Data
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *SMBUS_IO_DONE) (
+ IN UINT8 *StsReg
+ );
+
+#define PCH_SMBUS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('p', 's', 'm', 'b')
+
+/**
+ Get SMBUS IO Base address
+
+
+ @retval UINT32 The SMBUS IO Base Address
+**/
+UINT32
+SmbusGetIoBase (
+ VOID
+ );
+
+/**
+ This function provides a standard way to read PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+
+ @retval UINT8 Returns data read from IO.
+**/
+UINT8
+EFIAPI
+SmbusIoRead (
+ IN UINT8 Offset
+ );
+
+/**
+ This function provides a standard way to write PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+ @param[in] Data Data to write to register.
+
+**/
+VOID
+EFIAPI
+SmbusIoWrite (
+ IN UINT8 Offset,
+ IN UINT8 Data
+ );
+
+/**
+ This function provides a standard way to check if an SMBus transaction has
+ completed.
+
+ @param[in] StsReg Not used for input. On return, contains the
+ value of the SMBus status register.
+
+ @retval TRUE Transaction is complete
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+IoDone (
+ IN UINT8 *StsReg
+ );
+
+/**
+ Check if it's ok to use the bus.
+
+
+ @retval EFI_SUCCESS SmBus is acquired and it's safe to send commands.
+ @retval EFI_TIMEOUT SmBus is busy, it's not safe to send commands.
+**/
+EFI_STATUS
+AcquireBus (
+ VOID
+ );
+
+/**
+ This function provides a standard way to execute Smbus protocols
+ as defined in the SMBus Specification. The data can either be of
+ the Length byte, word, or a block of data. The resulting transaction will be
+ either the SMBus Slave Device accepts this transaction or this function
+ returns with an error
+
+ @param[in] SlaveAddress Smbus Slave device the command is directed at
+ @param[in] Command Slave Device dependent
+ @param[in] Operation Which SMBus protocol will be used
+ @param[in] PecCheck Defines if Packet Error Code Checking is to be used
+ @param[in, out] Length How many bytes to read. Must be 0 <= Length <= 32 depending on Operation
+ It will contain the actual number of bytes read/written.
+ @param[in, out] Buffer Contain the data read/written.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @exception EFI_UNSUPPORTED The operation is unsupported.
+
+ @retval EFI_INVALID_PARAMETER Length or Buffer is NULL for any operation besides
+ quick read or quick write.
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period, or the controller is not
+ available for use.
+ @retval EFI_DEVICE_ERROR There was an Smbus error (NACK) during the operation.
+ This could indicate the slave device is not present
+ or is in a hung condition.
+**/
+EFI_STATUS
+SmbusExec (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ This function initializes the Smbus Registers.
+
+**/
+VOID
+InitializeSmbusRegisters (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h
new file mode 100644
index 0000000000..8b6b6a6c97
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h
@@ -0,0 +1,401 @@
+/** @file
+ Header file for the PCH SPI Common Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SPI_COMMON_LIB_H_
+#define _PCH_SPI_COMMON_LIB_H_
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+// Wait Time = 6 seconds = 6000000 microseconds
+// Wait Period = 10 microseconds
+//
+#define WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds
+#define WAIT_PERIOD 10 ///< Wait Period = 10 microseconds
+
+///
+/// Flash cycle Type
+///
+typedef enum {
+ FlashCycleRead,
+ FlashCycleWrite,
+ FlashCycleErase,
+ FlashCycleReadSfdp,
+ FlashCycleReadJedecId,
+ FlashCycleWriteStatus,
+ FlashCycleReadStatus,
+ FlashCycleMax
+} FLASH_CYCLE_TYPE;
+
+///
+/// Flash Component Number
+///
+typedef enum {
+ FlashComponent0,
+ FlashComponent1,
+ FlashComponentMax
+} FLASH_COMPONENT_NUM;
+
+///
+/// Private data structure definitions for the driver
+///
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', 'I')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ PCH_SPI_PROTOCOL SpiProtocol;
+ UINT16 PchAcpiBase;
+ UINTN PchSpiBase;
+ UINT8 ReadPermission;
+ UINT8 WritePermission;
+ UINT32 SfdpVscc0Value;
+ UINT32 SfdpVscc1Value;
+ UINT16 PchStrapBaseAddr;
+ UINT16 PchStrapSize;
+ UINT16 CpuStrapBaseAddr;
+ UINT16 CpuStrapSize;
+ UINT8 NumberOfComponents;
+ UINT32 Component1StartAddr;
+ UINT32 TotalFlashSize;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+//
+// Function prototypes used by the SPI protocol.
+//
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ Acquire pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Release pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ );
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ );
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ );
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ );
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ );
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ );
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor
+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN FLASH_CYCLE_TYPE FlashCycleType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN OUT UINT8 *Buffer
+ );
+
+/**
+ Wait execution cycle to complete on the SPI interface.
+
+ @param[in] This The SPI protocol instance
+ @param[in] PchSpiBar0 Spi MMIO base address
+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN ErrorCheck
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h
new file mode 100644
index 0000000000..da4cfc6d19
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h
@@ -0,0 +1,49 @@
+/** @file
+ PEI I2C Master module
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_I2C_MASTER_LIB_H_
+#define _PEI_I2C_MASTER_LIB_H_
+
+#include <Ppi/I2cMaster.h>
+#include <Library/PchSerialIoLib.h>
+
+/*
+ Installs I2cMaster PPIs for each I2c controller.
+
+ @param[in] Controller - SerialIo controller number
+
+ @retval EFI_INVALID_PARAMETER - wrong Controller number
+ @retval EFI_ALREADY_STARTED - I2cMaster Ppi was already installed on given controller
+ @retval EFI_SUCCESS - I2cMaster Ppi succesfully installed
+ @retval any other return value - internal error of InstallPpi function
+*/
+EFI_STATUS
+InstallI2cMasterPpi (
+ PCH_SERIAL_IO_CONTROLLER Controller
+ );
+
+/*
+ Finds I2cMasterPpi instance for a specified controller
+
+ @param[in] Controller - SerialIo controller number
+
+ @retval NULL - couldn't locate I2cMaster Ppi for given controller
+ @retval not-NULL - pointer to I2cMaster Ppi
+*/
+EFI_PEI_I2C_MASTER_PPI*
+LocateI2cMasterPpi (
+ PCH_SERIAL_IO_CONTROLLER Controller
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h
new file mode 100644
index 0000000000..2301c9fc0f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h
@@ -0,0 +1,91 @@
+/** @file
+ Header file for Rst Library
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _RST_PRIVATE_LIB_
+#define _RST_PRIVATE_LIB_
+#include <Uefi/UefiBaseType.h>
+#include <Library/PchInfoLib.h>
+#include <PchLimits.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInitCommonLib.h>
+#include <PcieRegs.h>
+
+#define RST_PCIE_STORAGE_INTERFACE_NONE 0
+#define RST_PCIE_STORAGE_INTERFACE_AHCI 1
+#define RST_PCIE_STORAGE_INTERFACE_NVME 2
+
+#define RST_STONY_BEACH_VENDOR_ID 0x8086
+#define RST_STONY_BEACH_DEVICE_ID 0x2522
+
+#define PCI_CLASS_MASS_STORAGE_NVME 0x08
+#define PCI_CLASS_MASS_STORAGE_AHCI PCI_CLASS_MASS_STORAGE_SATADPA
+
+
+/**
+ Check if there is a remap capable storage device present on Root Port
+
+ @param[in] RpNumber Number of a Root Port to check
+ @param[in] TempPciBus Temporary Pci Bus Number
+
+ @retval UINT8 Device Programming interface, 0 if no remap capable device present
+
+**/
+UINT8
+RstGetProgInterfaceForRemapDevice (
+ IN UINT32 RpNumber,
+ IN UINT32 TempPciBus
+ );
+
+/**
+ Check the lane occupied by certain root port according to the root port number and configuration strap
+ Return 8-bit bitmap where each bit represents the lane number (e.g.: return 00000011b means the root port owns 2 lane)
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT8 Lane Occupied by the Root Port (bitmap)
+**/
+UINT8
+RstGetRpLaneOccupyMask (
+ IN UINT32 RootPortNum
+ );
+
+
+/**
+ Checks PCH generation and returns SATA's GCR.PLS bit number according to root port number with a PCIe storage device
+ connected to.
+
+ @param[in] RootPortNum Root port number which PCIe storage device is connected to
+
+ @retval UINT32 Number of GCR.PLS bit representing root port
+**/
+UINT32
+RstPlsBitNumber (
+ IN UINT32 RootPortNum
+ );
+
+/**
+ Checks if device with given PCI config space address is Intel's Stony Beach.
+
+ @param[in] EndPointPciBase Address of device's PCI config space
+
+ @retval BOOLEAN TRUE if device is Intel's Stony Beach, FALSE othrwise
+**/
+BOOLEAN
+RstIsStonyBeach (
+ IN UINTN EndPointPciBase
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h
new file mode 100644
index 0000000000..fb372e92ac
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h
@@ -0,0 +1,298 @@
+/** @file
+ The GUID definition for PchConfigHob
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_CONFIG_HOB_H_
+#define _PCH_CONFIG_HOB_H_
+
+#include <ConfigBlock.h>
+#include <PchAccess.h>
+#include <ConfigBlock/SmbusConfig.h>
+#include <ConfigBlock/InterruptConfig.h>
+#include <ConfigBlock/PcieRpConfig.h>
+#include <ConfigBlock/SataConfig.h>
+#include <ConfigBlock/FlashProtectionConfig.h>
+
+extern EFI_GUID gPchConfigHobGuid;
+
+#pragma pack (push,1)
+
+///
+/// This structure contains the HOB which are related to PCH general config.
+///
+typedef struct {
+ /**
+ This member describes whether or not the Compatibility Revision ID (CRID) feature
+ of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Crid : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} GENERAL_HOB;
+
+///
+/// The SMBUS_CONFIG block lists the reserved addresses for non-ARP capable devices in the platform.
+///
+typedef struct {
+ UINT8 RsvdBytes[3];
+ UINT8 NumRsvdSmbusAddresses; ///< The number of elements in the RsvdSmbusAddressTable.
+ /**
+ Array of addresses reserved for non-ARP-capable SMBus devices.
+ **/
+ UINT8 RsvdSmbusAddressTable[PCH_MAX_SMBUS_RESERVED_ADDRESS];
+} SMBUS_HOB;
+
+///
+/// The INTERRUPT describes interrupt settings for PCH HOB.
+///
+typedef struct {
+ UINT8 NumOfDevIntConfig; ///< Number of entries in DevIntConfig table
+ UINT8 GpioIrqRoute; ///< Interrupt routing for GPIO. Default is <b>14</b>.
+ UINT8 Rsvd0[2]; ///< Reserved bytes, align to multiple 4.
+ PCH_DEVICE_INTERRUPT_CONFIG DevIntConfig[PCH_MAX_DEVICE_INTERRUPT_CONFIG]; ///< Array which stores PCH devices interrupts settings
+} INTERRUPT_HOB;
+
+///
+/// The CIO2_HOB block describes SkyCam CIO2 device.
+///
+typedef struct {
+ /**
+ NOTE: For SKL PCH, while CIO2 is enabled,
+ RC will configure CIO2 controller as ACPI mode when PCH stepping < C0, and configure to PCI mode for C0 onwards.
+ **/
+ UINT32 DeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled</b>
+ UINT32 RsvdBits0 : 30;
+} CIO2_HOB;
+
+/**
+ The SERIAL_IO block provides the configurations to set the Serial IO controllers
+ to Acpi devices or Pci controllers, and also set the interrupt type to Acpi or Pci
+ through Policy. It also provides to configure the I2c0 and I2c1 voltage
+ to 1.8v or 3.3v by platform setting.
+ Please refer to PeiDxeSmmPchSerialIoLib.h for definition of device numbers and enum values for the below fields
+**/
+typedef struct {
+ /**
+ 0: Disabled; 1: ACPI Mode; <b>2: PCI Mode</b>; 3: Hidden mode, 4: Legacy UART mode, 5: Skip Init
+ NOTE: Considering the PcdSerialIoUartDebugEnable and PcdSerialIoUartNumber for all SerialIo UARTx,
+ the PCD is more meaningful to represent the board design. It means, if PcdSerialIoUartDebugEnable is not 0,
+ the board is designed to use the SerialIo UART for debug message and the PcdSerialIoUartNumber is dedicated
+ to be Debug UART usage. Therefore, it should grayout the option from setup menu since no other options
+ available for this UART controller on this board, and also override the policy default accordingly.
+ While PcdSerialIoUartDebugEnable is 0, then it's allowed to configure the UART controller by policy.
+ NOTE: While DevMode is set to 5 (Skip Init), BIOS will not initialize this controller. Platform is resonsible for
+ configuring this controller. If platform initializes the Serial IO controller in Hidden Mode, it MUST
+ follow the predefined BAR address for the controller.
+ **/
+ UINT8 DevMode[PCH_SERIALIO_MAX_CONTROLLERS]; ///< serial io max controllers default is <b>11</b>.
+ UINT8 Gpio; ///< 0: Disabled; <b>1: Enabled</b>.
+ UINT32 DebugUartNumber : 2; ///< UART number for debug purpose. 0:UART0, 1: UART1, <b>2:UART2</b>
+ UINT32 EnableDebugUartAfterPost : 1; ///< Enable debug UART controller after post. 0: diabled, <b>1: enabled</b>
+ UINT32 RsvdBits0 : 29;
+} SERIAL_IO_HOB;
+
+
+///
+/// The PCH_PCIE_CONFIG block describes the expected configuration of the PCH PCI Express controllers
+///
+typedef struct {
+ ///
+ /// These members describe the configuration of each PCH PCIe root port.
+ ///
+ PCH_PCIE_ROOT_PORT_CONFIG RootPort[PCH_MAX_PCIE_ROOT_PORTS];
+ /**
+ This member allows BIOS to control ICC PLL Shutdown by determining PCIe devices are LTR capable
+ or leaving untouched.
+ - <b>0: Disable, ICC PLL Shutdown is determined by PCIe device LTR capablility.</b>
+ - To allow ICC PLL shutdown if all present PCIe devices are LTR capable or if no PCIe devices are
+ presented for maximum power savings where possible.
+ - To disable ICC PLL shutdown when BIOS detects any non-LTR capable PCIe device for ensuring device
+ functionality.
+ - 1: Enable, To allow ICC PLL shutdown even if some devices do not support LTR capability.
+ **/
+ UINT32 AllowNoLtrIccPllShutdown : 1;
+ UINT32 RsvdBits0 : 31;
+} PCIERP_HOB;
+
+typedef struct {
+ UINT32 DspEnable : 1; ///< DSP enablement: 0: Disable; <b>1: Enable</b>
+ /**
+ Bitmask of supported DSP endpoint configuration exposed via NHLT ACPI table:
+ **/
+ UINT32 DspEndpointDmic : 2; ///< DMIC Select (PCH_HDAUDIO_DMIC_TYPE enum): 0: Disable; 1: 2ch array; <b>2: 4ch array</b>; 3: 1ch array
+ UINT32 DspEndpointBluetooth : 1; ///< Bluetooth enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 DspEndpointI2s : 1; ///< I2S enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 RsvdBits0 : 27; ///< Reserved bits
+ /**
+ Bitmask of supported DSP features:
+ [BIT0] - WoV; [BIT1] - BT Sideband; [BIT2] - Codec VAD; [BIT5] - BT Intel HFP; [BIT6] - BT Intel A2DP
+ [BIT7] - DSP based speech pre-processing disabled; [BIT8] - 0: Intel WoV, 1: Windows Voice Activation
+ Default is <b>zero</b>.
+ **/
+ UINT32 DspFeatureMask;
+} HDAUDIO_HOB;
+
+typedef struct {
+ ///
+ /// This member describes whether or not the SATA controllers should be enabled. 0: Disable; <b>1: Enable</b>.
+ ///
+ UINT32 Enable : 1;
+ UINT32 TestMode : 1; ///< <b>(Test)</b> <b>0: Disable</b>; 1: Allow entrance to the PCH SATA test modes
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+ /**
+ This member configures the features, property, and capability for each SATA port.
+ **/
+ PCH_SATA_PORT_CONFIG PortSettings[PCH_MAX_SATA_PORTS];
+ /**
+ This member describes the details of implementation of Intel RST for PCIe Storage remapping (Intel RST Driver is required)
+ **/
+ PCH_RST_PCIE_STORAGE_CONFIG RstPcieStorageRemap[PCH_MAX_RST_PCIE_STORAGE_CR];
+} SATA_HOB;
+
+/**
+ The THERMAL_HOB block describes the expected configuration of the PCH for Thermal.
+**/
+typedef struct {
+ UINT32 ThermalDeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled in PCI mode</b>, 2: Enabled in ACPI mode
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+} THERMAL_HOB;
+
+/**
+ This structure is used for the emulation feature for Port61h read. The port is trapped
+ and the SMI handler will toggle bit4 according to the handler's internal state.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b> the emulation
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PORT61H_SMM_HOB;
+
+///
+/// The SCS_HOB block describes Storage and Communication Subsystem (SCS) settings for PCH.
+///
+typedef struct {
+ UINT32 ScsEmmcEnabled : 2; ///< Determine if eMMC is enabled - 0: Disabled, <b>1: Enabled</b>.
+ UINT32 ScsEmmcHs400Enabled : 1; ///< Determine eMMC HS400 Mode if ScsEmmcEnabled - <b>0: Disabled</b>, 1: Enabled
+ /**
+ Determine if HS400 Training is required, set to FALSE if Hs400 Data is valid. <b>0: Disabled</b>, 1: Enabled.
+ First Boot or CMOS clear, system boot with Default settings, set tuning required.
+ Subsequent Boots, Get Variable 'Hs400TuningData'
+ - if failed to get variable, set tuning required
+ - if passed, retrieve Hs400DataValid, Hs400RxStrobe1Dll and Hs400TxDataDll from variable. Set tuning not required.
+ **/
+ UINT32 ScsEmmcHs400TuningRequired : 1;
+ UINT32 ScsEmmcHs400DllDataValid : 1; ///< Set if HS400 Tuning Data Valid
+ UINT32 ScsEmmcHs400DriverStrength : 3; ///< I/O driver strength: <b>0 - 33 Ohm</b>, 1 - 40 Ohm, 2 - 50 Ohm
+ UINT32 RsvdBits : 24;
+
+} SCS_HOB;
+
+/**
+ The PCH_LOCK_DOWN_CONFIG block describes the expected configuration of the PCH
+ for security requirement.
+**/
+typedef struct {
+ UINT32 GlobalSmi : 1;
+ /**
+ <b>(Test)</b> Enable BIOS Interface Lock Down bit to prevent writes to the Backup Control Register
+ Top Swap bit and the General Control and Status Registers Boot BIOS Straps. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosInterface : 1;
+ /**
+ <b>(Test)</b> Enable RTC lower and upper 128 byte Lock bits to lock Bytes 38h-3Fh in the upper
+ and lower 128-byte bank of RTC RAM. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 RtcLock : 1;
+ /**
+ Enable the BIOS Lock Enable (BLE) feature and set EISS bit (D31:F5:RegDCh[5])
+ for the BIOS region protection. When it is enabled, the BIOS Region can only be
+ modified from SMM after EndOfDxe protocol is installed.
+ Note: When BiosLock is enabled, platform code also needs to update to take care
+ of BIOS modification (including SetVariable) in DXE or runtime phase after
+ EndOfDxe protocol is installed. <b>0: Disable</b>; 1: Enable.
+ **/
+ UINT32 BiosLock : 1;
+ UINT32 RsvdBits : 28;
+} LOCK_DOWN_HOB;
+
+/**
+ The PM_HOB block describes expected miscellaneous power management settings.
+ The PowerResetStatusClear field would clear the Power/Reset status bits, please
+ set the bits if you want PCH Init driver to clear it, if you want to check the
+ status later then clear the bits.
+**/
+typedef struct {
+ /**
+ <b>(Test)</b>
+ When set to true, this bit disallows host reads to PMC XRAM.
+ BIOS must set this bit (to disable and lock the feature) prior to passing control to OS
+ 0:Disable, <b>1:Enable</b>
+ **/
+ UINT32 PmcReadDisable : 1;
+ UINT32 RsvdBits1 : 31;
+} PM_HOB;
+
+/**
+ This structure contains the HOB which are related to P2SB device.
+**/
+typedef struct {
+ /**
+ <b>(Test)</b>
+ This unlock the SBI lock bit to allow SBI after post time. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbiUnlock" unless necessary.
+ **/
+ UINT32 SbiUnlock : 1;
+ /**
+ <b>(Test)</b>
+ The PSF registers will be locked before 3rd party code execution.
+ This policy unlock the PSF space. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbAccessUnlock" unless necessary.
+ **/
+ UINT32 PsfUnlock : 1; //@deprecated
+ UINT32 SbAccessUnlock : 1;
+ UINT32 RsvdBits : 29;
+} P2SB_HOB;
+
+/**
+ This structure holds information about disabled USB2 and USB3 ports through Port Disable Override functionality
+**/
+typedef struct {
+ UINT32 DelayPdoProgramming : 1; ///< Flag informing about delaying PDO programming to DXE phase
+ UINT32 Usb2DisabledPorts : 16; ///< USB2 Disabled ports
+ UINT32 Usb3DisabledPorts : 10; ///< USB3 Disabled ports
+ UINT32 RsvdBits : 5;
+} USB_HOB;
+
+
+///
+/// Pch Config Hob
+///
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID HOB type structure for gPchConfigHobGuid
+ GENERAL_HOB General; ///< Pch general HOB definition
+ INTERRUPT_HOB Interrupt; ///< Interrupt HOB definition
+ SERIAL_IO_HOB SerialIo; ///< Serial io HOB definition
+ PCIERP_HOB PcieRp; ///< PCIE root port HOB definition
+ THERMAL_HOB Thermal; ///< Thermal HOB definition
+ SCS_HOB Scs; ///< Scs HOB definition
+ CIO2_HOB Cio2; ///< CIO2 HOB definition
+ LOCK_DOWN_HOB LockDown; ///< Lock down HOB definition
+ PM_HOB Pm; ///< PM HOB definition
+ P2SB_HOB P2sb; ///< P2sb HOB definition
+ HDAUDIO_HOB HdAudio; ///< HD audio definition
+ SATA_HOB Sata; ///< SATA definition
+ PROTECTED_RANGE ProtectRange[PCH_FLASH_PROTECTED_RANGES];
+ PORT61H_SMM_HOB Port61hSmm;
+ SMBUS_HOB Smbus;
+ USB_HOB Usb;
+
+} PCH_CONFIG_HOB;
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h
new file mode 100644
index 0000000000..97f7be6c11
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h
@@ -0,0 +1,129 @@
+/** @file
+ Header file for PchHdaLib Endpoint descriptors.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_HDA_ENDPOINTS_H_
+#define _PCH_HDA_ENDPOINTS_H_
+
+#include <Library/DxePchHdaNhlt.h>
+
+typedef enum {
+ HdaDmicX1 = 0,
+ HdaDmicX2,
+ HdaDmicX4,
+ HdaBtRender,
+ HdaBtCapture,
+ HdaI2sRender1,
+ HdaI2sRender2,
+ HdaI2sCapture,
+ HdaEndpointMax
+} NHLT_ENDPOINT;
+
+typedef struct {
+ NHLT_ENDPOINT EndpointType;
+ UINT32 EndpointFormatsBitmask;
+ BOOLEAN Enable;
+} PCH_HDA_NHLT_ENDPOINTS;
+
+#define PCH_HDA_NHLT_TABLE_SIZE 0x2000
+
+// Format bitmask
+#define B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT BIT0
+#define B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT BIT1
+#define B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT BIT2
+#define B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT BIT3
+#define B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT BIT4
+#define B_HDA_BT_NARROWBAND_FORMAT BIT5
+#define B_HDA_BT_WIDEBAND_FORMAT BIT6
+#define B_HDA_BT_A2DP_FORMAT BIT7
+#define B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT BIT8
+#define B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT BIT9
+#define B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT BIT10
+#define B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT BIT11
+#define B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT BIT12
+#define B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT BIT13
+#define B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT BIT14
+#define B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT BIT15
+#define V_HDA_FORMAT_MAX 16
+
+// Formats
+extern CONST WAVEFORMATEXTENSIBLE Ch1_48kHz16bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch2_48kHz16bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch2_48kHz24bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch2_48kHz32bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch4_48kHz16bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch4_48kHz32bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE NarrowbandFormat;
+extern CONST WAVEFORMATEXTENSIBLE WidebandFormat;
+extern CONST WAVEFORMATEXTENSIBLE A2dpFormat;
+
+// Format Config
+extern CONST UINT32 DmicStereo16BitFormatConfig[];
+extern CONST UINT32 DmicStereo16BitFormatConfigSize;
+extern CONST UINT32 DmicStereo32BitFormatConfig[];
+extern CONST UINT32 DmicStereo32BitFormatConfigSize;
+extern CONST UINT32 DmicQuad16BitFormatConfig[];
+extern CONST UINT32 DmicQuad16BitFormatConfigSize;
+extern CONST UINT32 DmicQuad32BitFormatConfig[];
+extern CONST UINT32 DmicQuad32BitFormatConfigSize;
+extern CONST UINT32 DmicMono16BitFormatConfig[];
+extern CONST UINT32 DmicMono16BitFormatConfigSize;
+extern CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfig[];
+extern CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfigSize;
+extern CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfig[];
+extern CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfigSize;
+extern CONST UINT32 I2sRtk286S2ch48kHzFormatConfig[];
+extern CONST UINT32 I2sRtk286S2ch48kHzFormatConfigSize;
+extern CONST UINT32 I2sAdi4ch48kHzFormatConfig[];
+extern CONST UINT32 I2sAdi4ch48kHzFormatConfigSize;
+extern CONST UINT32 I2s48kHz24bitMasterFormatConfig[];
+extern CONST UINT32 I2s48kHz24bitMasterFormatConfigSize;
+extern CONST UINT32 I2s48kHz24bitSlaveFormatConfig[];
+extern CONST UINT32 I2s48kHz24bitSlaveFormatConfigSize;
+extern CONST UINT32 I2sPcm8kHz16bitMasterFormatConfig[];
+extern CONST UINT32 I2sPcm8kHz16bitMasterFormatConfigSize;
+extern CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfig[];
+extern CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfigSize;
+extern CONST UINT32 BtFormatConfig[];
+extern CONST UINT32 BtFormatConfigSize;
+
+// Endpoints
+extern ENDPOINT_DESCRIPTOR HdaEndpointDmicX1;
+extern ENDPOINT_DESCRIPTOR HdaEndpointDmicX2;
+extern ENDPOINT_DESCRIPTOR HdaEndpointDmicX4;
+extern ENDPOINT_DESCRIPTOR HdaEndpointBtRender;
+extern ENDPOINT_DESCRIPTOR HdaEndpointBtCapture;
+extern ENDPOINT_DESCRIPTOR HdaEndpointI2sRender;
+extern ENDPOINT_DESCRIPTOR HdaEndpointI2sCapture;
+
+// Endpoint Config
+extern CONST UINT8 DmicX1Config[];
+extern CONST UINT32 DmicX1ConfigSize;
+extern CONST UINT8 DmicX2Config[];
+extern CONST UINT32 DmicX2ConfigSize;
+extern CONST UINT8 DmicX4Config[];
+extern CONST UINT32 DmicX4ConfigSize;
+extern CONST UINT8 BtConfig[];
+extern CONST UINT32 BtConfigSize;
+extern CONST UINT8 I2sRender1Config[];
+extern CONST UINT32 I2sRender1ConfigSize;
+extern CONST UINT8 I2sRender2Config[];
+extern CONST UINT32 I2sRender2ConfigSize;
+extern CONST UINT8 I2sCaptureConfig[];
+extern CONST UINT32 I2sCaptureConfigSize;
+
+// Oed Configuration
+extern CONST UINT32 NhltConfiguration[];
+extern CONST UINT32 NhltConfigurationSize;
+
+#endif // _PCH_HDA_ENDPOINTS_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h
new file mode 100644
index 0000000000..ac288a56d0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h
@@ -0,0 +1,33 @@
+/** @file
+ This file defines the PCH NVS Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_NVS_H_
+#define _PCH_NVS_H_
+
+#include "PchNvsArea.h"
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchNvsAreaProtocolGuid;
+
+/**
+ This protocol is used to sync PCH information from POST to runtime ASL.
+ This protocol exposes the pointer of PCH NVS Area only. Please refer to
+ ASL definition for PCH NVS AREA.
+**/
+typedef struct {
+ PCH_NVS_AREA *Area;
+} PCH_NVS_AREA_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h
new file mode 100644
index 0000000000..66c119f577
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h
@@ -0,0 +1,243 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+ //
+ // Define PCH NVS Area operatino region.
+ //
+
+#ifndef _PCH_NVS_AREA_H_
+#define _PCH_NVS_AREA_H_
+
+#pragma pack (push,1)
+typedef struct {
+ UINT16 PchSeries; ///< Offset 0 PCH Series
+ UINT16 PchGeneration; ///< Offset 2 PCH Generation
+ UINT32 RpAddress[24]; ///< Offset 4 Root Port address 1
+ ///< Offset 8 Root Port address 2
+ ///< Offset 12 Root Port address 3
+ ///< Offset 16 Root Port address 4
+ ///< Offset 20 Root Port address 5
+ ///< Offset 24 Root Port address 6
+ ///< Offset 28 Root Port address 7
+ ///< Offset 32 Root Port address 8
+ ///< Offset 36 Root Port address 9
+ ///< Offset 40 Root Port address 10
+ ///< Offset 44 Root Port address 11
+ ///< Offset 48 Root Port address 12
+ ///< Offset 52 Root Port address 13
+ ///< Offset 56 Root Port address 14
+ ///< Offset 60 Root Port address 15
+ ///< Offset 64 Root Port address 16
+ ///< Offset 68 Root Port address 17
+ ///< Offset 72 Root Port address 18
+ ///< Offset 76 Root Port address 19
+ ///< Offset 80 Root Port address 20
+ ///< Offset 84 Root Port address 21
+ ///< Offset 88 Root Port address 22
+ ///< Offset 92 Root Port address 23
+ ///< Offset 96 Root Port address 24
+ UINT64 NHLA; ///< Offset 100 HD-Audio NHLT ACPI address
+ UINT32 NHLL; ///< Offset 108 HD-Audio NHLT ACPI length
+ UINT32 ADFM; ///< Offset 112 HD-Audio DSP Feature Mask
+ UINT32 SBRG; ///< Offset 116 SBREG_BAR
+ UINT32 GPEM; ///< Offset 120 GPP_X to GPE_DWX mapping
+ UINT32 GP2T[10]; ///< Offset 124 GPE 2-tier level edged enabled Gpio pads (Group Index 0)
+ ///< Offset 128 GPE 2-tier level edged enabled Gpio pads (Group Index 1)
+ ///< Offset 132 GPE 2-tier level edged enabled Gpio pads (Group Index 2)
+ ///< Offset 136 GPE 2-tier level edged enabled Gpio pads (Group Index 3)
+ ///< Offset 140 GPE 2-tier level edged enabled Gpio pads (Group Index 4)
+ ///< Offset 144 GPE 2-tier level edged enabled Gpio pads (Group Index 5)
+ ///< Offset 148 GPE 2-tier level edged enabled Gpio pads (Group Index 6)
+ ///< Offset 152 GPE 2-tier level edged enabled Gpio pads (Group Index 7)
+ ///< Offset 156 GPE 2-tier level edged enabled Gpio pads (Group Index 8)
+ ///< Offset 160 GPE 2-tier level edged enabled Gpio pads (Group Index 9)
+ UINT16 PcieLtrMaxSnoopLatency[24]; ///< Offset 164 PCIE LTR max snoop Latency 1
+ ///< Offset 166 PCIE LTR max snoop Latency 2
+ ///< Offset 168 PCIE LTR max snoop Latency 3
+ ///< Offset 170 PCIE LTR max snoop Latency 4
+ ///< Offset 172 PCIE LTR max snoop Latency 5
+ ///< Offset 174 PCIE LTR max snoop Latency 6
+ ///< Offset 176 PCIE LTR max snoop Latency 7
+ ///< Offset 178 PCIE LTR max snoop Latency 8
+ ///< Offset 180 PCIE LTR max snoop Latency 9
+ ///< Offset 182 PCIE LTR max snoop Latency 10
+ ///< Offset 184 PCIE LTR max snoop Latency 11
+ ///< Offset 186 PCIE LTR max snoop Latency 12
+ ///< Offset 188 PCIE LTR max snoop Latency 13
+ ///< Offset 190 PCIE LTR max snoop Latency 14
+ ///< Offset 192 PCIE LTR max snoop Latency 15
+ ///< Offset 194 PCIE LTR max snoop Latency 16
+ ///< Offset 196 PCIE LTR max snoop Latency 17
+ ///< Offset 198 PCIE LTR max snoop Latency 18
+ ///< Offset 200 PCIE LTR max snoop Latency 19
+ ///< Offset 202 PCIE LTR max snoop Latency 20
+ ///< Offset 204 PCIE LTR max snoop Latency 21
+ ///< Offset 206 PCIE LTR max snoop Latency 22
+ ///< Offset 208 PCIE LTR max snoop Latency 23
+ ///< Offset 210 PCIE LTR max snoop Latency 24
+ UINT16 PcieLtrMaxNoSnoopLatency[24]; ///< Offset 212 PCIE LTR max no snoop Latency 1
+ ///< Offset 214 PCIE LTR max no snoop Latency 2
+ ///< Offset 216 PCIE LTR max no snoop Latency 3
+ ///< Offset 218 PCIE LTR max no snoop Latency 4
+ ///< Offset 220 PCIE LTR max no snoop Latency 5
+ ///< Offset 222 PCIE LTR max no snoop Latency 6
+ ///< Offset 224 PCIE LTR max no snoop Latency 7
+ ///< Offset 226 PCIE LTR max no snoop Latency 8
+ ///< Offset 228 PCIE LTR max no snoop Latency 9
+ ///< Offset 230 PCIE LTR max no snoop Latency 10
+ ///< Offset 232 PCIE LTR max no snoop Latency 11
+ ///< Offset 234 PCIE LTR max no snoop Latency 12
+ ///< Offset 236 PCIE LTR max no snoop Latency 13
+ ///< Offset 238 PCIE LTR max no snoop Latency 14
+ ///< Offset 240 PCIE LTR max no snoop Latency 15
+ ///< Offset 242 PCIE LTR max no snoop Latency 16
+ ///< Offset 244 PCIE LTR max no snoop Latency 17
+ ///< Offset 246 PCIE LTR max no snoop Latency 18
+ ///< Offset 248 PCIE LTR max no snoop Latency 19
+ ///< Offset 250 PCIE LTR max no snoop Latency 20
+ ///< Offset 252 PCIE LTR max no snoop Latency 21
+ ///< Offset 254 PCIE LTR max no snoop Latency 22
+ ///< Offset 256 PCIE LTR max no snoop Latency 23
+ ///< Offset 258 PCIE LTR max no snoop Latency 24
+ UINT32 SerialIoDebugUart0Bar0; ///< Offset 260 SerialIo Hidden UART0 BAR 0
+ UINT32 SerialIoDebugUart1Bar0; ///< Offset 264 SerialIo Hidden UART1 BAR 0
+ UINT8 XHPC; ///< Offset 268 Number of HighSpeed ports implemented in XHCI controller
+ UINT8 XRPC; ///< Offset 269 Number of USBR ports implemented in XHCI controller
+ UINT8 XSPC; ///< Offset 270 Number of SuperSpeed ports implemented in XHCI controller
+ UINT8 XSPA; ///< Offset 271 Address of 1st SuperSpeed port
+ UINT32 HPTB; ///< Offset 272 HPET base address
+ UINT8 HPTE; ///< Offset 276 HPET enable
+ //SerialIo block
+ UINT8 SMD[11]; ///< Offset 277 SerialIo controller 0 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 278 SerialIo controller 1 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 279 SerialIo controller 2 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 280 SerialIo controller 3 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 281 SerialIo controller 4 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 282 SerialIo controller 5 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 283 SerialIo controller 6 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 284 SerialIo controller 7 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 285 SerialIo controller 8 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 286 SerialIo controller 9 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 287 SerialIo controller A mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ UINT8 SIR[11]; ///< Offset 288 SerialIo controller 0 irq number
+ ///< Offset 289 SerialIo controller 1 irq number
+ ///< Offset 290 SerialIo controller 2 irq number
+ ///< Offset 291 SerialIo controller 3 irq number
+ ///< Offset 292 SerialIo controller 4 irq number
+ ///< Offset 293 SerialIo controller 5 irq number
+ ///< Offset 294 SerialIo controller 6 irq number
+ ///< Offset 295 SerialIo controller 7 irq number
+ ///< Offset 296 SerialIo controller 8 irq number
+ ///< Offset 297 SerialIo controller 9 irq number
+ ///< Offset 298 SerialIo controller A irq number
+ UINT64 SB0[11]; ///< Offset 299 SerialIo controller 0 BAR0
+ ///< Offset 307 SerialIo controller 1 BAR0
+ ///< Offset 315 SerialIo controller 2 BAR0
+ ///< Offset 323 SerialIo controller 3 BAR0
+ ///< Offset 331 SerialIo controller 4 BAR0
+ ///< Offset 339 SerialIo controller 5 BAR0
+ ///< Offset 347 SerialIo controller 6 BAR0
+ ///< Offset 355 SerialIo controller 7 BAR0
+ ///< Offset 363 SerialIo controller 8 BAR0
+ ///< Offset 371 SerialIo controller 9 BAR0
+ ///< Offset 379 SerialIo controller A BAR0
+ UINT64 SB1[11]; ///< Offset 387 SerialIo controller 0 BAR1
+ ///< Offset 395 SerialIo controller 1 BAR1
+ ///< Offset 403 SerialIo controller 2 BAR1
+ ///< Offset 411 SerialIo controller 3 BAR1
+ ///< Offset 419 SerialIo controller 4 BAR1
+ ///< Offset 427 SerialIo controller 5 BAR1
+ ///< Offset 435 SerialIo controller 6 BAR1
+ ///< Offset 443 SerialIo controller 7 BAR1
+ ///< Offset 451 SerialIo controller 8 BAR1
+ ///< Offset 459 SerialIo controller 9 BAR1
+ ///< Offset 467 SerialIo controller A BAR1
+ //end of SerialIo block
+ UINT8 GPEN; ///< Offset 475 GPIO enabled
+ UINT8 SGIR; ///< Offset 476 GPIO IRQ
+ UINT8 RstPcieStorageInterfaceType[3]; ///< Offset 477 RST PCIe Storage Cycle Router#1 Interface Type
+ ///< Offset 478 RST PCIe Storage Cycle Router#2 Interface Type
+ ///< Offset 479 RST PCIe Storage Cycle Router#3 Interface Type
+ UINT8 RstPcieStoragePmCapPtr[3]; ///< Offset 480 RST PCIe Storage Cycle Router#1 Power Management Capability Pointer
+ ///< Offset 481 RST PCIe Storage Cycle Router#2 Power Management Capability Pointer
+ ///< Offset 482 RST PCIe Storage Cycle Router#3 Power Management Capability Pointer
+ UINT8 RstPcieStoragePcieCapPtr[3]; ///< Offset 483 RST PCIe Storage Cycle Router#1 PCIe Capabilities Pointer
+ ///< Offset 484 RST PCIe Storage Cycle Router#2 PCIe Capabilities Pointer
+ ///< Offset 485 RST PCIe Storage Cycle Router#3 PCIe Capabilities Pointer
+ UINT16 RstPcieStorageL1ssCapPtr[3]; ///< Offset 486 RST PCIe Storage Cycle Router#1 L1SS Capability Pointer
+ ///< Offset 488 RST PCIe Storage Cycle Router#2 L1SS Capability Pointer
+ ///< Offset 490 RST PCIe Storage Cycle Router#3 L1SS Capability Pointer
+ UINT8 RstPcieStorageEpL1ssControl2[3]; ///< Offset 492 RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data2
+ ///< Offset 493 RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data2
+ ///< Offset 494 RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data2
+ UINT32 RstPcieStorageEpL1ssControl1[3]; ///< Offset 495 RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data1
+ ///< Offset 499 RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data1
+ ///< Offset 503 RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data1
+ UINT16 RstPcieStorageLtrCapPtr[3]; ///< Offset 507 RST PCIe Storage Cycle Router#1 LTR Capability Pointer
+ ///< Offset 509 RST PCIe Storage Cycle Router#2 LTR Capability Pointer
+ ///< Offset 511 RST PCIe Storage Cycle Router#3 LTR Capability Pointer
+ UINT32 RstPcieStorageEpLtrData[3]; ///< Offset 513 RST PCIe Storage Cycle Router#1 Endpoint LTR Data
+ ///< Offset 517 RST PCIe Storage Cycle Router#2 Endpoint LTR Data
+ ///< Offset 521 RST PCIe Storage Cycle Router#3 Endpoint LTR Data
+ UINT16 RstPcieStorageEpLctlData16[3]; ///< Offset 525 RST PCIe Storage Cycle Router#1 Endpoint LCTL Data
+ ///< Offset 527 RST PCIe Storage Cycle Router#2 Endpoint LCTL Data
+ ///< Offset 529 RST PCIe Storage Cycle Router#3 Endpoint LCTL Data
+ UINT16 RstPcieStorageEpDctlData16[3]; ///< Offset 531 RST PCIe Storage Cycle Router#1 Endpoint DCTL Data
+ ///< Offset 533 RST PCIe Storage Cycle Router#2 Endpoint DCTL Data
+ ///< Offset 535 RST PCIe Storage Cycle Router#3 Endpoint DCTL Data
+ UINT16 RstPcieStorageEpDctl2Data16[3]; ///< Offset 537 RST PCIe Storage Cycle Router#1 Endpoint DCTL2 Data
+ ///< Offset 539 RST PCIe Storage Cycle Router#2 Endpoint DCTL2 Data
+ ///< Offset 541 RST PCIe Storage Cycle Router#3 Endpoint DCTL2 Data
+ UINT16 RstPcieStorageRpDctl2Data16[3]; ///< Offset 543 RST PCIe Storage Cycle Router#1 RootPort DCTL2 Data
+ ///< Offset 545 RST PCIe Storage Cycle Router#2 RootPort DCTL2 Data
+ ///< Offset 547 RST PCIe Storage Cycle Router#3 RootPort DCTL2 Data
+ UINT32 RstPcieStorageUniqueTableBar[3]; ///< Offset 549 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR
+ ///< Offset 553 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR
+ ///< Offset 557 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR
+ UINT32 RstPcieStorageUniqueTableBarValue[3]; ///< Offset 561 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR value
+ ///< Offset 565 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR value
+ ///< Offset 569 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR value
+ UINT32 RstPcieStorageUniquePbaBar[3]; ///< Offset 573 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR
+ ///< Offset 577 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR
+ ///< Offset 581 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR
+ UINT32 RstPcieStorageUniquePbaBarValue[3]; ///< Offset 585 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR value
+ ///< Offset 589 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR value
+ ///< Offset 593 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR value
+ UINT32 RstPcieStorageRootPortNum[3]; ///< Offset 597 RST PCIe Storage Cycle Router#1 Root Port number
+ ///< Offset 601 RST PCIe Storage Cycle Router#2 Root Port number
+ ///< Offset 605 RST PCIe Storage Cycle Router#3 Root Port number
+ UINT8 ExitBootServicesFlag; ///< Offset 609 Flag indicating Exit Boot Service, to inform SMM
+ UINT32 SxMemBase; ///< Offset 610 Sx handler reserved MMIO base
+ UINT32 SxMemSize; ///< Offset 614 Sx handler reserved MMIO size
+ UINT8 Cio2EnabledAsAcpiDevice; ///< Offset 618 Cio2 Device Enabled as ACPI device
+ UINT8 Cio2IrqNumber; ///< Offset 619 Cio2 Interrupt Number
+ UINT8 ThermalDeviceAcpiEnabled; ///< Offset 620 Thermal Device Acpi mode enabled
+ UINT8 ThermalDeviceInterruptLine; ///< Offset 621 Thermal Device IRQ number
+ UINT32 XhciRsvdMemBase; ///< Offset 622 XHCI memory base address
+ UINT8 EMH4; ///< Offset 626 eMMC HS400 mode enabled
+ UINT8 EMDS; ///< Offset 627 eMMC Driver Strength
+ UINT8 CpuSku; ///< Offset 628 CPU SKU
+ UINT16 IoTrapAddress[4]; ///< Offset 629
+ ///< Offset 631
+ ///< Offset 633
+ ///< Offset 635
+ UINT8 IoTrapStatus[4]; ///< Offset 637
+ ///< Offset 638
+ ///< Offset 639
+ ///< Offset 640
+ UINT16 PMBS; ///< Offset 641 ACPI IO BASE address
+ UINT32 PWRM; ///< Offset 643 PWRM MEM BASE address
+} PCH_NVS_AREA;
+
+#pragma pack(pop)
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h
new file mode 100644
index 0000000000..26d13b7a7d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h
@@ -0,0 +1,42 @@
+/** @file
+ This file defines the PCH PCIE IoTrap Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PCIE_IOTRAP_H_
+#define _PCH_PCIE_IOTRAP_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchPcieIoTrapProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_PCIE_IOTRAP_PROTOCOL PCH_PCIE_IOTRAP_PROTOCOL;
+
+///
+/// Pcie Trap valid types
+///
+typedef enum {
+ PciePmTrap,
+ PcieTrapTypeMaximum
+} PCH_PCIE_TRAP_TYPE;
+
+/**
+ This protocol is used to provide the IoTrap address to trigger PCH PCIE call back events
+**/
+struct _PCH_PCIE_IOTRAP_PROTOCOL {
+ UINT16 PcieTrapAddress;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
new file mode 100644
index 0000000000..ec1a69e4de
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
@@ -0,0 +1,161 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <PchAccess.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mBaseResetSystemABase;
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT32 Data32;
+
+ ABase = mBaseResetSystemABase;
+ if (ABase == 0) {
+ PchAcpiBaseGet (&ABase);
+ }
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (ABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library instance.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+**/
+EFI_STATUS
+EFIAPI
+BaseResetSystemLibConstructor (
+ VOID
+ )
+{
+ PchAcpiBaseGet (&mBaseResetSystemABase);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
new file mode 100644
index 0000000000..2af43b5091
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+CONSTRUCTOR = BaseResetSystemLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+PciLib
+BaseLib
+DebugLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseResetSystemLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c
new file mode 100644
index 0000000000..17e42dfd0b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c
@@ -0,0 +1,996 @@
+/** @file
+ PCH SMBUS library implementation built upon I/O library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Library/SmbusLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/DebugLib.h>
+#include <PchAccess.h>
+#include <Library/MmPciLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mSmbusIoBase = 0;
+
+/**
+ Gets Io port base address of Smbus Host Controller.
+
+ @retval The Io port base address of Smbus host controller.
+
+**/
+UINT16
+InternalGetSmbusIoPortBaseAddress (
+ VOID
+ )
+{
+ UINTN SmbusPciBase;
+ UINT16 IoPortBaseAddress;
+
+ if (mSmbusIoBase != 0) {
+ return mSmbusIoBase;
+ }
+
+ SmbusPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ IoPortBaseAddress = (UINT16) MmioRead32 (SmbusPciBase + R_PCH_SMBUS_BASE);
+
+ //
+ // Make sure that the IO port base address has been properly set.
+ //
+ if ((IoPortBaseAddress == 0) || (IoPortBaseAddress == 0xFFFF)) {
+ ASSERT (FALSE);
+ return 0;
+ }
+
+ IoPortBaseAddress &= B_PCH_SMBUS_BASE_BAR;
+ mSmbusIoBase = IoPortBaseAddress;
+
+ return IoPortBaseAddress;
+}
+
+
+/**
+ Acquires the ownership of SMBUS.
+
+ This internal function reads the host state register.
+ If the SMBUS is not available, RETURN_TIMEOUT is returned;
+ Otherwise, it performs some basic initializations and returns
+ RETURN_SUCCESS.
+
+ @param[in] IoPortBaseAddress The Io port base address of Smbus Host controller.
+
+ @retval RETURN_SUCCESS The SMBUS command was executed successfully.
+ @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.
+
+**/
+RETURN_STATUS
+InternalSmBusAcquire (
+ IN UINT16 IoPortBaseAddress
+ )
+{
+ UINT8 HostStatus;
+
+ HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
+ if ((HostStatus & B_PCH_SMBUS_IUS) != 0) {
+ return RETURN_TIMEOUT;
+ } else if ((HostStatus & B_PCH_SMBUS_HBSY) != 0) {
+ //
+ // Clear host status register and exit.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ return RETURN_TIMEOUT;
+ }
+ //
+ // Clear out any odd status information (Will Not Clear In Use).
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, HostStatus);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Starts the SMBUS transaction and waits until the end.
+
+ This internal function start the SMBUS transaction and waits until the transaction
+ of SMBUS is over by polling the INTR bit of Host status register.
+ If the SMBUS is not available, RETURN_TIMEOUT is returned;
+ Otherwise, it performs some basic initializations and returns
+ RETURN_SUCCESS.
+
+ @param[in] IoPortBaseAddress The Io port base address of Smbus Host controller.
+ @param[in] HostControl The Host control command to start SMBUS transaction.
+
+ @retval RETURN_SUCCESS The SMBUS command was executed successfully.
+ @retval RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect).
+ @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected
+ in the Host Status Register bit. Device errors are
+ a result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+
+**/
+RETURN_STATUS
+InternalSmBusStart (
+ IN UINT16 IoPortBaseAddress,
+ IN UINT8 HostControl
+ )
+{
+ UINT8 HostStatus;
+ UINT8 AuxiliaryStatus;
+
+ //
+ // Set Host Control Register (Initiate Operation, Interrupt disabled).
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL, (UINT8)(HostControl + B_PCH_SMBUS_START));
+
+ do {
+ //
+ // Poll INTR bit of Host Status Register.
+ //
+ HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
+ } while ((HostStatus & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_ERROR | B_PCH_SMBUS_BYTE_DONE_STS)) == 0);
+
+ if ((HostStatus & B_PCH_SMBUS_ERROR) == 0) {
+ return RETURN_SUCCESS;
+ }
+ //
+ // Clear error bits of Host Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_ERROR);
+ //
+ // Read Auxiliary Status Register to judge CRC error.
+ //
+ AuxiliaryStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS);
+ if ((AuxiliaryStatus & B_PCH_SMBUS_CRCE) != 0) {
+ return RETURN_CRC_ERROR;
+ }
+
+ return RETURN_DEVICE_ERROR;
+}
+
+/**
+ Executes an SMBUS quick, byte or word command.
+
+ This internal function executes an SMBUS quick, byte or word commond.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+
+ @param[in] HostControl The value of Host Control Register to set.
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The byte/word write to the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte/word read from the SMBUS.
+
+**/
+UINT16
+InternalSmBusNonBlock (
+ IN UINT8 HostControl,
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status
+ )
+{
+ RETURN_STATUS ReturnStatus;
+ UINT16 IoPortBaseAddress;
+ UINT8 AuxiliaryControl;
+
+ IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
+
+ //
+ // Try to acquire the ownership of SMBUS.
+ //
+ ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+ //
+ // Set the appropriate Host Control Register and auxiliary Control Register.
+ //
+ AuxiliaryControl = 0;
+ if (SMBUS_LIB_PEC (SmBusAddress)) {
+ AuxiliaryControl |= B_PCH_SMBUS_AAC;
+ HostControl |= B_PCH_SMBUS_PEC_EN;
+ }
+ //
+ // Set Host Commond Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
+ //
+ // Write value to Host Data 0 and Host Data 1 Registers.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) Value);
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD1, (UINT8) (Value >> 8));
+ //
+ // Set Auxiliary Control Regiester.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
+ //
+ // Set SMBUS slave address for the device to send/receive from.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
+ //
+ // Start the SMBUS transaction and wait for the end.
+ //
+ ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
+ //
+ // Read value from Host Data 0 and Host Data 1 Registers.
+ //
+ Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD1) << 8);
+ Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0));
+ //
+ // Clear Host Status Register and Auxiliary Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+
+Done:
+ if (Status != NULL) {
+ *Status = ReturnStatus;
+ }
+
+ return Value;
+}
+
+/**
+ Executes an SMBUS quick read command.
+
+ Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If PEC is set in SmBusAddress, then ASSERT().
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+SmBusQuickRead (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if (SMBUS_LIB_PEC (SmBusAddress) ||
+ (SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return;
+ }
+
+ InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_QUICK,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS quick write command.
+
+ Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If PEC is set in SmBusAddress, then ASSERT().
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+SmBusQuickWrite (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if (SMBUS_LIB_PEC (SmBusAddress) ||
+ (SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return;
+ }
+
+ InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_QUICK,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS receive byte command.
+
+ Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ The byte received from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte received from the SMBUS.
+
+**/
+UINT8
+EFIAPI
+SmBusReceiveByte (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS send byte command.
+
+ Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.
+ The byte specified by Value is sent.
+ Only the SMBUS slave address field of SmBusAddress is required. Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 8-bit value to send.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The parameter of Value.
+
+**/
+UINT8
+EFIAPI
+SmBusSendByte (
+ IN UINTN SmBusAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS read data byte command.
+
+ Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 8-bit value read from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte read from the SMBUS.
+
+**/
+UINT8
+EFIAPI
+SmBusReadDataByte (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write data byte command.
+
+ Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.
+ The 8-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 8-bit value to write.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The parameter of Value.
+
+**/
+UINT8
+EFIAPI
+SmBusWriteDataByte (
+ IN UINTN SmBusAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS read data word command.
+
+ Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 16-bit value read from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte read from the SMBUS.
+
+**/
+UINT16
+EFIAPI
+SmBusReadDataWord (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_WORD_DATA,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write data word command.
+
+ Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.
+ The 16-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 16-bit value to write.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+SmBusWriteDataWord (
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_WORD_DATA,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS process call command.
+
+ Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.
+ The 16-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 16-bit value returned by the process call command is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 16-bit value to write.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The 16-bit value returned by the process call command.
+
+**/
+UINT16
+EFIAPI
+SmBusProcessCall (
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_PROCESS_CALL,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS block command.
+
+ Executes an SMBUS block read, block write and block write-block read command
+ on the SMBUS device specified by SmBusAddress.
+ Bytes are read from the SMBUS and stored in Buffer.
+ The number of bytes read is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+
+ @param[in] HostControl The value of Host Control Register to set.
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
+ @param[out] ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes read from the SMBUS.
+
+**/
+UINTN
+InternalSmBusBlock (
+ IN UINT8 HostControl,
+ IN UINTN SmBusAddress,
+ IN UINT8 *WriteBuffer,
+ OUT UINT8 *ReadBuffer,
+ OUT RETURN_STATUS *Status
+ )
+{
+ RETURN_STATUS ReturnStatus;
+ UINTN Index;
+ UINTN BytesCount;
+ UINT16 IoPortBaseAddress;
+ UINT8 AuxiliaryControl;
+
+ IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
+
+ BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);
+
+ //
+ // Try to acquire the ownership of SMBUS.
+ //
+ ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+ //
+ // Set the appropriate Host Control Register and auxiliary Control Register.
+ //
+ AuxiliaryControl = B_PCH_SMBUS_E32B;
+ if (SMBUS_LIB_PEC (SmBusAddress)) {
+ AuxiliaryControl |= B_PCH_SMBUS_AAC;
+ HostControl |= B_PCH_SMBUS_PEC_EN;
+ }
+ //
+ // Set Host Command Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
+ //
+ // Set Auxiliary Control Regiester.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
+ //
+ // Clear byte pointer of 32-byte buffer.
+ //
+ IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL);
+
+ if (WriteBuffer != NULL) {
+ //
+ // Write the number of block to Host Block Data Byte Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) BytesCount);
+ //
+ // Write data block to Host Block Data Register.
+ //
+ for (Index = 0; Index < BytesCount; Index++) {
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HBD, WriteBuffer[Index]);
+ }
+ }
+ //
+ // Set SMBUS slave address for the device to send/receive from.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
+ //
+ // Start the SMBUS transaction and wait for the end.
+ //
+ ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+
+ if (ReadBuffer != NULL) {
+ //
+ // Read the number of block from host block data byte register.
+ //
+ BytesCount = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0);
+ //
+ // Write data block from Host Block Data Register.
+ //
+ for (Index = 0; Index < BytesCount; Index++) {
+ ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HBD);
+ }
+ }
+
+Done:
+ //
+ // Clear Host Status Register and Auxiliary Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+
+ if (Status != NULL) {
+ *Status = ReturnStatus;
+ }
+
+ return BytesCount;
+}
+
+/**
+ Executes an SMBUS read block command.
+
+ Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Bytes are read from the SMBUS and stored in Buffer.
+ The number of bytes read is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If Buffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Buffer Pointer to the buffer to store the bytes read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes read.
+
+**/
+UINTN
+EFIAPI
+SmBusReadBlock (
+ IN UINTN SmBusAddress,
+ OUT VOID *Buffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (Buffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((Buffer == NULL) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusBlock (
+ V_PCH_SMBUS_SMB_CMD_BLOCK,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ NULL,
+ Buffer,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write block command.
+
+ Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.
+ The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
+ Bytes are written to the SMBUS from Buffer.
+ The number of bytes written is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is zero or greater than 32, then ASSERT().
+ If Buffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Buffer Pointer to the buffer to store the bytes read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes written.
+
+**/
+UINTN
+EFIAPI
+SmBusWriteBlock (
+ IN UINTN SmBusAddress,
+ OUT VOID *Buffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (Buffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((Buffer == NULL) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) == 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) > 32) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusBlock (
+ V_PCH_SMBUS_SMB_CMD_BLOCK,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Buffer,
+ NULL,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS block process call command.
+
+ Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress.
+ The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
+ Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+ If Length in SmBusAddress is zero or greater than 32, then ASSERT().
+ If WriteBuffer is NULL, then ASSERT().
+ If ReadBuffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
+ @param[out] ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes written.
+
+**/
+UINTN
+EFIAPI
+SmBusBlockProcessCall (
+ IN UINTN SmBusAddress,
+ IN VOID *WriteBuffer,
+ OUT VOID *ReadBuffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (WriteBuffer != NULL);
+ ASSERT (ReadBuffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((WriteBuffer == NULL) ||
+ (ReadBuffer == NULL) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) == 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) > 32) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusBlock (
+ V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ WriteBuffer,
+ ReadBuffer,
+ Status
+ );
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library instance.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+**/
+RETURN_STATUS
+EFIAPI
+BaseSmbusLibConstructor (
+ VOID
+ )
+{
+ UINTN SmbusPciBase;
+ UINT16 IoPortBaseAddress;
+
+ //
+ // Init mSmbusIoBase variable.
+ //
+ SmbusPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ IoPortBaseAddress = (UINT16) MmioRead32 (SmbusPciBase + R_PCH_SMBUS_BASE);
+
+ if ((IoPortBaseAddress != 0) && (IoPortBaseAddress != 0xFFFF)) {
+ mSmbusIoBase = IoPortBaseAddress & B_PCH_SMBUS_BASE_BAR;
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf
new file mode 100644
index 0000000000..a737f7105f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for PCH Smbus Library.
+#
+# SMBUS Library that layers on top of the I/O Library to directly
+# access a standard SMBUS host controller.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSmbusLib
+FILE_GUID = 5C4D0430-F81B-42D3-BB88-4A6CD2796FF8
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SmbusLib
+CONSTRUCTOR = BaseSmbusLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+BaseLib
+DebugLib
+IoLib
+MmPciLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+BaseSmbusLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c
new file mode 100644
index 0000000000..9526560b95
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c
@@ -0,0 +1,325 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <PchAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Protocol/PchReset.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mDxeResetSystemPmcBase;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDxeResetSystemABase;
+
+/**
+ Dump reset message for debug build readability
+**/
+VOID
+DumpResetMessage (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+ //
+ // ******************************
+ // ** SYSTEM REBOOT !!! **
+ // ******************************
+ //
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n"));
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+**/
+EFI_STATUS
+EFIAPI
+PchResetCallback (
+ IN PCH_RESET_TYPE ResetType
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ PCH_RESET_CALLBACK_PROTOCOL *PchResetCallback;
+
+ ///
+ /// Retrieve all instances of Pch Reset Callback protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gPchResetCallbackProtocolGuid,
+ NULL,
+ &NumHandles,
+ &HandleBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ///
+ /// Those drivers that need to install Pch Reset Callback protocol have the responsibility
+ /// to make sure themselves execute before Reset driver.
+ ///
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "None of Pch Reset Callback protocol is installed.\n"));
+ }
+ return Status;
+ }
+
+ for (Index = 0; Index < NumHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gPchResetCallbackProtocolGuid,
+ (VOID **) &PchResetCallback
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ PchResetCallback->ResetCallback (ResetType);
+ } else {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "Failed to locate Pch Reset Callback protocol.\n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetCold);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetWarm);
+
+ DumpResetMessage ();
+ //
+ // In case there are pending capsules to process, need to flush the cache.
+ //
+ AsmWbinvd ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetShutdown);
+
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ DumpResetMessage ();
+
+ IoWrite32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Internal function to execute the required HECI command for GlobalReset,
+ if failed will use PCH Reest.
+
+**/
+STATIC
+VOID
+DxePchGlobalReset (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback (PchGlobalReset);
+
+ //
+ // PCH BIOS Spec Section 4.6 GPIO Reset Requirement
+ //
+ MmioOr32 (mDxeResetSystemPmcBase + R_PCH_PMC_ETR3, (UINT32) B_PCH_PMC_ETR3_CF9GR);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ EFI_GUID *GuidPtr;
+
+ if (ResetData == NULL) {
+ DEBUG ((DEBUG_ERROR, "[DxeResetSystemLib] ResetData is not available.\n"));
+ return;
+ }
+ GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
+ if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
+ DxePchGlobalReset();
+ } else {
+ return;
+ }
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library DXE instance.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+**/
+EFI_STATUS
+EFIAPI
+DxeResetSystemLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Get ACPI Base Address and PMC Base Address
+ //
+ PchAcpiBaseGet (&mDxeResetSystemABase);
+
+ mDxeResetSystemPmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf
new file mode 100644
index 0000000000..1736c3189e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf
@@ -0,0 +1,56 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeResetSystemLib
+FILE_GUID = 239383BC-499E-4DC5-8CDC-F85AF27B1BC4
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+CONSTRUCTOR = DxeResetSystemLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+TimerLib
+BaseMemoryLib
+UefiBootServicesTableLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeResetSystemLib.c
+
+
+[Protocols]
+gPchResetCallbackProtocolGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c
new file mode 100644
index 0000000000..919cb407e0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c
@@ -0,0 +1,367 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <PchAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Protocol/PchReset.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mDxeRuntimeResetSystemPmcBase;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDxeRuntimeResetSystemABase;
+
+/**
+ Dump reset message for debug build readability
+**/
+VOID
+DumpResetMessage (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+ //
+ // ******************************
+ // ** SYSTEM REBOOT !!! **
+ // ******************************
+ //
+ if (!EfiAtRuntime ()) {
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n"));
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+ DEBUG_CODE_END ();
+}
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+**/
+EFI_STATUS
+EFIAPI
+PchResetCallback (
+ IN PCH_RESET_TYPE ResetType
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ PCH_RESET_CALLBACK_PROTOCOL *PchResetCallback;
+
+ if (!EfiAtRuntime ()) {
+ ///
+ /// Retrieve all instances of Pch Reset Callback protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gPchResetCallbackProtocolGuid,
+ NULL,
+ &NumHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ ///
+ /// Those drivers that need to install Pch Reset Callback protocol have the responsibility
+ /// to make sure themselves execute before Pch Reset Runtime driver.
+ ///
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "None of Pch Reset Callback protocol is installed.\n"));
+ }
+ return Status;
+ }
+
+ for (Index = 0; Index < NumHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gPchResetCallbackProtocolGuid,
+ (VOID **) &PchResetCallback
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ PchResetCallback->ResetCallback (ResetType);
+ } else {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "Failed to locate Pch Reset Callback protocol.\n"));
+ return Status;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetCold);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetWarm);
+
+ DumpResetMessage ();
+ //
+ // In case there are pending capsules to process, need to flush the cache.
+ //
+ AsmWbinvd ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetShutdown);
+
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ DumpResetMessage ();
+
+ IoWrite32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Internal function to execute the required HECI command for GlobalReset,
+ if failed will use PCH Reest.
+
+**/
+STATIC
+VOID
+DxeRuntimePchGlobalReset (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback (PchGlobalReset);
+
+ //
+ // PCH BIOS Spec Section 4.6 GPIO Reset Requirement
+ //
+ MmioOr32 (mDxeRuntimeResetSystemPmcBase + R_PCH_PMC_ETR3, (UINT32) B_PCH_PMC_ETR3_CF9GR);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ EFI_GUID *GuidPtr;
+
+ if (ResetData == NULL) {
+ if (!EfiAtRuntime ()) {
+ DEBUG ((DEBUG_ERROR, "[DxeRuntimeResetSystemLib] ResetData is not available.\n"));
+ }
+ return;
+ }
+ GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
+ if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
+ DxeRuntimePchGlobalReset();
+ } else {
+ return;
+ }
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Convert the physical PMC base addresses to virtual addresses.
+
+ @param[in] Event The event that is being processed.
+ @param[in] Context The Event Context.
+**/
+VOID
+EFIAPI
+ResetSystemLibVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID **) &mDxeRuntimeResetSystemPmcBase);
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library instance.
+
+ The PMC PCI configuration space memory range is converted into EFI_RUNTIME_XXX
+ in PciHostBridgeEntryPoint
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+ @retval EFI_ERROR Please reference LocateProtocol for error code details.
+**/
+EFI_STATUS
+EFIAPI
+DxeRuntimeResetSystemLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT AddressChangeEvent;
+
+ //
+ // Get ACPI Base Address and PMC Base Address
+ //
+ PchAcpiBaseGet (&mDxeRuntimeResetSystemABase);
+
+ mDxeRuntimeResetSystemPmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ //
+ // Create Address Change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ResetSystemLibVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &AddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf
new file mode 100644
index 0000000000..801876dd93
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeRuntimeResetSystemLib
+FILE_GUID = 1026813A-E46F-43D1-B709-FF1F996F2E72
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_RUNTIME_DRIVER
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+CONSTRUCTOR = DxeRuntimeResetSystemLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+TimerLib
+BaseMemoryLib
+UefiRuntimeLib
+UefiBootServicesTableLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeRuntimeResetSystemLib.c
+
+
+[Protocols]
+gPchResetCallbackProtocolGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
+gEfiEventVirtualAddressChangeGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c
new file mode 100644
index 0000000000..6e0c1c8b46
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c
@@ -0,0 +1,505 @@
+/** @file
+ This file contains routines for GPIO initialization
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "GpioLibrary.h"
+
+/**
+ This procedure will handle requirement on gSPIx_CSB pins.
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO PadMode value
+ @param[in out] Dw0Reg Value for PADCFG_DW0 register
+ @param[in out] Dw0RegMask Mask of bits which will change in PADCFG_DWO register
+
+ @retval None
+**/
+STATIC
+VOID
+GpioHandleGSpiCSBPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadMode,
+ IN OUT UINT32 *Dw0Reg,
+ IN OUT UINT32 *Dw0RegMask
+ )
+{
+ //
+ // For gSPIx_CSB pins if are going to be used in native mode then skip setting
+ // pad mode here.
+ //
+ if (GpioIsGpioPadAGSpiCsbPin (GpioPad, PadMode)) {
+ //
+ // Skip setting PadMode to native, leave it in GPIO mode.
+ // Setting it to native should be done after Serial IO initialization
+ //
+ *Dw0RegMask |= B_PCH_GPIO_PAD_MODE;
+ *Dw0Reg &= ~B_PCH_GPIO_PAD_MODE;
+ *Dw0Reg |= ((GpioPadModeGpio >> 1) << N_PCH_GPIO_PAD_MODE);
+ }
+}
+
+/**
+ This procedure will handle requirement on SATA DEVSLPx pins.
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO PadMode value
+ @param[in out] Dw0Reg Value for PADCFG_DW0 register
+ @param[in out] Dw0RegMask Mask of bits which will change in PADCFG_DWO register
+
+ @retval None
+
+**/
+STATIC
+VOID
+GpioHandleSataDevSlpPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadMode,
+ IN OUT UINT32 *Dw0Reg,
+ IN OUT UINT32 *Dw0RegMask
+ )
+{
+ //
+ // For SATA DEVSLPx pins if used in native 1 mode then ensure that PadRstCfg
+ // is set to "00" - Powergood
+ //
+ if (GpioIsPadASataDevSlpPin (GpioPad, PadMode)) {
+ //
+ // Set PadRstCfg to Powergood
+ //
+ *Dw0RegMask |= B_PCH_GPIO_RST_CONF;
+ *Dw0Reg &= ~B_PCH_GPIO_RST_CONF;
+ *Dw0Reg |= ((GpioResumeReset >> 1) << N_PCH_GPIO_RST_CONF);
+ }
+}
+
+//
+// GPIO_DW_REG_VALUE structure is used by GpioConfigureSklPch function
+// to cache values which will be programmed into respective GPIO registers
+// after all GpioPads are processed. This way MMIO accesses are decreased
+// and instead of doing one programming for one GpioPad there is only
+// one access for whole register.
+//
+typedef struct {
+ UINT32 HostSoftOwnReg;
+ UINT32 HostSoftOwnRegMask;
+ UINT32 GpiGpeEnReg;
+ UINT32 GpiGpeEnRegMask;
+ UINT32 GpiNmiEnReg;
+ UINT32 GpiNmiEnRegMask;
+ UINT32 PadsToLock;
+ UINT32 PadsToLockTx;
+} GPIO_DW_REG_VALUE;
+
+//
+// GPIO_DW_REG_NUMBER contains number of DWords required to
+// store Pad data for all groups. Each pad uses one bit.
+//
+// For Skylake and Kabylake each group has <32 pads what
+// makes GPIO_DW_REG_NUMBER = 1
+//
+#define GPIO_DW_REG_NUMBER 1
+
+/**
+ Get GPIO DW Register values (HOSTSW_OWN, GPE_EN, NMI_EN, Lock).
+
+ @param[in] PadNumber GPIO pad number
+ @param[in] GpioConfig GPIO Config data
+ @param[in out] DwRegsValues Values for GPIO DW Registers
+
+ @retval None
+**/
+STATIC
+VOID
+GpioDwRegValueFromGpioConfig (
+ IN UINT32 PadNumber,
+ IN GPIO_CONFIG *GpioConfig,
+ IN OUT GPIO_DW_REG_VALUE *DwRegsValues
+ )
+{
+ UINT32 PadBitPosition;
+ UINT32 DwNum;
+
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+
+ if (DwNum >= GPIO_DW_REG_NUMBER) {
+ ASSERT (FALSE);
+ return;
+ }
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ DwRegsValues[DwNum].HostSoftOwnRegMask |= (GpioConfig->HostSoftPadOwn & 0x1) << PadBitPosition;
+ DwRegsValues[DwNum].HostSoftOwnReg |= (GpioConfig->HostSoftPadOwn >> 0x1) << PadBitPosition;
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ DwRegsValues[DwNum].GpiGpeEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
+ DwRegsValues[DwNum].GpiGpeEnReg |= ((GpioConfig->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition;
+
+ //
+ // Update value to be programmed in GPI_NMI_EN register
+ //
+ DwRegsValues[DwNum].GpiNmiEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
+ DwRegsValues[DwNum].GpiNmiEnReg |= ((GpioConfig->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition;
+
+ //
+ // Update information on Pad Configuration Lock
+ //
+ DwRegsValues[DwNum].PadsToLock |= ((GpioConfig->LockConfig >> 0x1) & 0x1) << PadBitPosition;
+
+ //
+ // Update information on Pad Configuration Lock Tx
+ //
+ DwRegsValues[DwNum].PadsToLockTx |= ((GpioConfig->LockConfig >> 0x2) & 0x1) << PadBitPosition;
+}
+
+/**
+ This SKL PCH specific procedure will initialize multiple SKL PCH GPIO pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+STATIC
+EFI_STATUS
+GpioConfigureSklPch (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ UINT32 Index;
+ UINT32 PadCfgDwReg[2];
+ UINT32 PadCfgDwRegMask[2];
+ UINT32 PadCfgReg;
+ GPIO_DW_REG_VALUE DwRegsValues[GPIO_DW_REG_NUMBER];
+ UINT32 DwNum;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ GPIO_GROUP GpioGroupOffset;
+ UINT32 NumberOfGroups;
+ GPIO_PAD_OWN PadOwnVal;
+ GPIO_INIT_CONFIG *GpioData;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ PadOwnVal = GpioPadOwnHost;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ Index = 0;
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ Group = GpioGetGroupFromGpioPad (GpioData->GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+
+ if (GroupIndex >= V_PCH_GPIO_GROUP_MAX) {
+ // @todo SKL PCH: one platform code ready we should add this back ASSERT (FALSE);
+ continue;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ if (!(((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID (GpioData->GpioPad) == GPIO_SKL_H_CHIPSET_ID)) ||
+ ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID (GpioData->GpioPad) == GPIO_SKL_LP_CHIPSET_ID)))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGroupOffset) || (Group >= NumberOfGroups + GpioGroupOffset)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Invalid group %d\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (DwRegsValues, sizeof (DwRegsValues));
+ //
+ // Loop through pads for one group. If pad belongs to a different group then
+ // break and move to register programming.
+ //
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ if (GroupIndex != GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)) {
+ //if next pad is from different group then break loop
+ break;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for group %d\n", PadNumber, GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ //
+ GpioGetPadOwnership (GpioData->GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ DEBUG ((DEBUG_ERROR, "** Please make sure the GPIO usage in sync between CSME and BIOS configuration. \n"));
+ DEBUG ((DEBUG_ERROR, "** All the GPIO occupied by CSME should not do any configuration by BIOS.\n"));
+ //Move to next item
+ Index++;
+ continue;
+ }
+ DEBUG_CODE_END ();
+
+ ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
+ ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
+ //
+ // Get GPIO PADCFG register value from GPIO config data
+ //
+ GpioPadCfgRegValueFromGpioConfig (
+ GpioData->GpioPad,
+ &GpioData->GpioConfig,
+ PadCfgDwReg,
+ PadCfgDwRegMask
+ );
+
+ //
+ // Check for additional requirements on setting PADCFG register
+ //
+ GpioHandleGSpiCSBPad (GpioData->GpioPad, GpioData->GpioConfig.PadMode, &PadCfgDwReg[0], &PadCfgDwRegMask[0]);
+ GpioHandleSataDevSlpPad (GpioData->GpioPad, GpioData->GpioConfig.PadMode, &PadCfgDwReg[0], &PadCfgDwRegMask[0]);
+
+ //
+ // Create PADCFG register offset using group and pad number
+ //
+ PadCfgReg = PAD_CFG_SIZE * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ //
+ // Write PADCFG DW0 register
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ ~PadCfgDwRegMask[0],
+ PadCfgDwReg[0]
+ );
+
+ //
+ // Write PADCFG DW1 register
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg + 0x4),
+ ~PadCfgDwRegMask[1],
+ PadCfgDwReg[1]
+ );
+
+ //
+ // Get GPIO DW register values from GPIO config data
+ //
+ GpioDwRegValueFromGpioConfig (
+ PadNumber,
+ &GpioData->GpioConfig,
+ DwRegsValues
+ );
+
+ //Move to next item
+ Index++;
+ }
+
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ //
+ // Write HOSTSW_OWN registers
+ //
+ if (GpioGroupInfo[GroupIndex].HostOwnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].HostOwnOffset + DwNum * 0x4),
+ ~DwRegsValues[DwNum].HostSoftOwnRegMask,
+ DwRegsValues[DwNum].HostSoftOwnReg
+ );
+ }
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeEnOffset + DwNum * 0x4),
+ ~DwRegsValues[DwNum].GpiGpeEnRegMask,
+ DwRegsValues[DwNum].GpiGpeEnReg
+ );
+ }
+
+ //
+ // Write GPI_NMI_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].NmiEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].NmiEnOffset + DwNum * 0x4),
+ ~DwRegsValues[DwNum].GpiNmiEnRegMask,
+ DwRegsValues[DwNum].GpiNmiEnReg
+ );
+ } else if (DwRegsValues[DwNum].GpiNmiEnReg != 0x0) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GroupIndex));
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ }
+
+ //
+ // Write Pad Configuration Lock
+ //
+ if (DwRegsValues[DwNum].PadsToLock != 0) {
+ GpioLockPadCfgForGroupDw (GroupIndex + GpioGroupOffset, DwNum, DwRegsValues[DwNum].PadsToLock);
+ }
+
+ //
+ // Write Pad Configuration Lock Tx
+ //
+ if (DwRegsValues[DwNum].PadsToLockTx != 0) {
+ GpioLockPadCfgTxForGroupDw (GroupIndex + GpioGroupOffset, DwNum, DwRegsValues[DwNum].PadsToLockTx);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear all status bits of any GPIO interrupts.
+
+ @param[in] none
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+STATIC
+EFI_STATUS
+GpioClearAllGpioInterrupts (
+ VOID
+ )
+{
+ GPIO_GROUP Group;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+ UINT32 GroupIndex;
+ UINTN GpioGroupInfoLength;
+ UINT32 DwNum;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ for (Group = GpioGroupLowest; Group <= GpioGroupHighest; Group++) {
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ //
+ // Check if group has GPI IS register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiIsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_IS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiIsOffset + DwNum * 0x4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has GPI_GPE_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_GPE_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeStsOffset + DwNum * 0x4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has SMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].SmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all SMI_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset + DwNum * 4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has NMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].NmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all NMI_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].NmiStsOffset + DwNum * 4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG structure.
+ Structure contains fields that can be used to configure each pad.
+ Pad not configured using GPIO_INIT_CONFIG will be left with hardware default values.
+ Separate fields could be set to hardware default if it does not matter, except
+ GpioPad and PadMode.
+ Some GpioPads are configured and switched to native mode by RC, those include:
+ SerialIo pins, ISH pins, ClkReq Pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ EFI_STATUS Status;
+ Status = GpioConfigureSklPch (NumberOfItems, GpioInitTableAddress);
+ GpioClearAllGpioInterrupts ();
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c
new file mode 100644
index 0000000000..bf76d40963
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c
@@ -0,0 +1,2691 @@
+/** @file
+ This file contains routines for GPIO
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "GpioLibrary.h"
+
+/**
+ This procedure will check if GpioPad is owned by host.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is owned by host
+ @retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadHostOwned (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_PAD_OWN PadOwnVal;
+
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ // If GPIO is not owned by Host all access to PadCfg will be dropped
+ //
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Gpio pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will check if GpioPad argument is valid.
+ Function will check below conditions:
+ - GpioPad represents a pad for current PCH
+ - GpioPad belongs to valid GpioGroup
+ - GPIO PadNumber is not greater than number of pads for this group
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is valid and can be used with GPIO lib API
+ @retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadValid (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return FALSE;
+ }
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return FALSE;
+ }
+
+ if ((GroupIndex < GpioGetGroupIndexFromGroup (GpioGetLowestGroup ())) ||
+ (GroupIndex > GpioGetGroupIndexFromGroup (GpioGetHighestGroup ()))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range of possible groups for this PCH\n", GroupIndex));
+ return FALSE;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will check if GpioGroup argument is correct and
+ supplied DW reg number can be used for this group to access DW registers.
+ Function will check below conditions:
+ - Valid GpioGroup
+ - DwNum is has valid value for this group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+
+ @retval TRUE DW Reg number and GpioGroup is valid
+ @retval FALSE DW Reg number and GpioGroup is invalid
+**/
+STATIC
+BOOLEAN
+GpioIsGroupAndDwNumValid (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum
+ )
+{
+ UINT32 GroupIndex;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return FALSE;
+ }
+
+ if ((GroupIndex < GpioGetGroupIndexFromGroup (GpioGetLowestGroup ())) ||
+ (GroupIndex > GpioGetGroupIndexFromGroup (GpioGetHighestGroup ()))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range of possible groups for this PCH\n", GroupIndex));
+ return FALSE;
+ }
+
+ //
+ // Check if DwNum argument does not exceed number of DWord registers
+ // resulting from available pads for certain group
+ //
+ if (DwNum > GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup - 1)){
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[out] PadCfgRegValue Read data
+
+ @retval none
+**/
+VOID
+GpioReadPadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ OUT UINT32 *PadCfgRegValue
+ )
+{
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + PAD_CFG_SIZE * PadNumber + 0x4 * DwReg;
+
+ *PadCfgRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+}
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
+ @param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
+
+ @retval none
+**/
+VOID
+GpioWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 PadCfgAndMask,
+ IN UINT32 PadCfgOrMask
+ )
+{
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + PAD_CFG_SIZE * PadNumber + 0x4 * DwReg;
+
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ PadCfgAndMask,
+ PadCfgOrMask
+ );
+}
+
+//
+// Possible registers to be accessed using GpioReadReg()/GpioWriteReg() functions
+//
+typedef enum {
+ GpioHostOwnershipRegister = 0,
+ GpioGpeEnableRegister,
+ GpioGpeStatusRegister,
+ GpioSmiEnableRegister,
+ GpioSmiStatusRegister,
+ GpioNmiEnableRegister,
+ GpioPadConfigLockRegister,
+ GpioPadLockOutputRegister
+} GPIO_REG;
+
+/**
+ This procedure will read GPIO register
+
+ @param[in] RegType GPIO register type
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] ReadVal Read data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioReadReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *ReadVal
+ )
+{
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioHostOwnershipRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
+ break;
+ case GpioGpeEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
+ break;
+ case GpioGpeStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
+ break;
+ case GpioSmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ break;
+ case GpioSmiStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
+ break;
+ case GpioNmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
+ break;
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ if ((RegType == GpioPadConfigLockRegister) || (RegType == GpioPadLockOutputRegister)) {
+ //
+ // PadConfigLock and OutputLock registers when used for group containing more than 32 pads
+ // are not placed in a continuous way, e.g:
+ // 0x0 - PadConfigLock_DW0
+ // 0x4 - OutputLock_DW0
+ // 0x8 - PadConfigLock_DW1
+ // 0xC - OutputLock_DW1
+ //
+ RegOffset += DwNum * 0x8;
+ } else {
+ RegOffset += DwNum * 0x4;
+ }
+
+ *ReadVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write GPIO register
+
+ @param[in] RegType GPIO register type
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] RegAndMask Mask which will be AND'ed with register value
+ @param[in] RegOrMask Mask which will be OR'ed with register value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioWriteReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 RegAndMask,
+ IN UINT32 RegOrMask
+ )
+{
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioHostOwnershipRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
+ break;
+ case GpioGpeEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
+ break;
+ case GpioGpeStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
+ break;
+ case GpioSmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ break;
+ case GpioSmiStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
+ break;
+ case GpioNmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
+ break;
+ case GpioPadConfigLockRegister:
+ case GpioPadLockOutputRegister:
+ ASSERT (FALSE);
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ RegOffset += DwNum * 0x4;
+
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset),
+ RegAndMask,
+ RegOrMask
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write GPIO Lock/LockTx register using SBI.
+
+ @param[in] RegType GPIO register (Lock or LockTx)
+ @param[in] Group GPIO group number
+ @param[in] DwNum Register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] LockRegAndMask Mask which will be AND'ed with Lock register value
+ @param[in] LockRegOrMask Mask which will be Or'ed with Lock register value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioWriteLockReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 LockRegAndMask,
+ IN UINT32 LockRegOrMask
+ )
+{
+ UINT8 Response;
+ EFI_STATUS Status;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 RegOffset;
+ UINT32 OldPadCfgLockRegVal;
+ UINT32 NewPadCfgLockRegVal;
+ UINT32 GroupIndex;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ // PadConfigLock and OutputLock registers when used for group containing more than 32 pads
+ // are not placed in a continuous way, e.g:
+ // 0x0 - PadConfigLock_DW0
+ // 0x4 - OutputLock_DW0
+ // 0x8 - PadConfigLock_DW1
+ // 0xC - OutputLock_DW1
+ //
+ RegOffset += DwNum *0x8;
+
+ GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldPadCfgLockRegVal);
+
+ NewPadCfgLockRegVal = (OldPadCfgLockRegVal & LockRegAndMask) | LockRegOrMask;
+
+ Status = PchSbiExecution (
+ GpioGroupInfo[GroupIndex].Community,
+ RegOffset,
+ GpioLockUnlock,
+ FALSE,
+ &NewPadCfgLockRegVal,
+ &Response
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This internal procedure will calculate GPIO_RESET_CONFIG value (new type)
+ based on provided PadRstCfg for a specific GPIO Pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadRstCfg GPIO PadRstCfg value
+
+ @retval GpioResetConfig GPIO Reset configuration (new type)
+**/
+GPIO_RESET_CONFIG
+GpioResetConfigFromPadRstCfg (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadRstCfg
+ )
+{
+ GPIO_GROUP Group;
+
+ static GPIO_RESET_CONFIG GppPadRstCfgToGpioResetConfigMap[] = {
+ GpioResumeReset,
+ GpioHostDeepReset,
+ GpioPlatformReset};
+ static GPIO_RESET_CONFIG GpdPadRstCfgToGpioResetConfigMap[] = {
+ GpioDswReset,
+ GpioHostDeepReset,
+ GpioPlatformReset,
+ GpioResumeReset};
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ ASSERT (PadRstCfg < 4);
+ if (PadRstCfg >= 4) return GpioResumeReset;
+ return GpdPadRstCfgToGpioResetConfigMap[PadRstCfg];
+ } else {
+ ASSERT (PadRstCfg < 3);
+ if (PadRstCfg >= 3) return GpioResumeReset;
+ return GppPadRstCfgToGpioResetConfigMap[PadRstCfg];
+ }
+}
+
+/**
+ This internal procedure will calculate PadRstCfg register value based
+ on provided GPIO Reset configuration for a certain pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioResetConfig GPIO Reset configuration
+ @param[out] PadRstCfg GPIO PadRstCfg value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid configuration
+**/
+EFI_STATUS
+GpioPadRstCfgFromResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG GpioResetConfig,
+ OUT UINT32 *PadRstCfg
+ )
+{
+ GPIO_GROUP Group;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ switch (GpioResetConfig) {
+ case GpioResetDefault:
+ *PadRstCfg = 0x0;
+ break;
+ case GpioResetPwrGood: //old reset type
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
+ break;
+ case GpioResetDeep: //old reset type
+ case GpioHostDeepReset: //new reset type
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_DEEP_RST;
+ break;
+ case GpioResetNormal: //old reset type
+ case GpioPlatformReset: //new reset type
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_GPIO_RST;
+ break;
+ case GpioResetResume: //old reset type
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_RESUME_RST;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioResetResume (Group=%d, Pad=%d)!\n", GpioGetGroupIndexFromGpioPad (GpioPad), GpioGetPadNumberFromGpioPad (GpioPad)));
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ case GpioResumeReset: //new reset type
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_RESUME_RST;
+ } else {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
+ }
+ break;
+ case GpioDswReset: //new reset type
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioDswReset (Group=%d, Pad=%d)!\n", GpioGetGroupIndexFromGpioPad (GpioPad), GpioGetPadNumberFromGpioPad (GpioPad)));
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This internal procedure will get GPIO_CONFIG data from PADCFG registers value
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadCfgDwReg PADCFG DWx register values
+ @param[out] GpioData GPIO Configuration data
+
+ @retval Status
+**/
+STATIC
+VOID
+GpioConfigFromPadCfgRegValue (
+ IN GPIO_PAD GpioPad,
+ IN CONST UINT32 *PadCfgDwReg,
+ OUT GPIO_CONFIG *GpioConfig
+ )
+{
+ UINT32 PadRstCfg;
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ PadRstCfg = (PadCfgDwReg[0] & B_PCH_GPIO_RST_CONF) >> N_PCH_GPIO_RST_CONF;
+
+ GpioConfig->PowerConfig = GpioResetConfigFromPadRstCfg (
+ GpioPad,
+ PadRstCfg
+ );
+
+ //
+ // Get how interrupt is triggered (RxEvCfg)
+ //
+ GpioConfig->InterruptConfig = ((PadCfgDwReg[0] & B_PCH_GPIO_RX_LVL_EDG) >> (N_PCH_GPIO_RX_LVL_EDG - (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS);
+
+ //
+ // Get interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ GpioConfig->InterruptConfig |= ((PadCfgDwReg[0] & (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE)) >> (N_PCH_GPIO_RX_NMI_ROUTE - (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS);
+
+ //
+ // Get GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ GpioConfig->Direction = ((PadCfgDwReg[0] & (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS)) >> (N_PCH_GPIO_TXDIS - (N_GPIO_DIRECTION_DIR_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_DIR_BIT_POS);
+
+ //
+ // Get GPIO input inversion (RXINV)
+ // (Only meaningful if input enabled)
+ //
+ if((PadCfgDwReg[0] & B_PCH_GPIO_RXDIS) == 0) {
+ GpioConfig->Direction |= ((PadCfgDwReg[0] & B_PCH_GPIO_RXINV) >> (N_PCH_GPIO_RXINV - (N_GPIO_DIRECTION_INV_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_INV_BIT_POS);
+ }
+
+ //
+ // Get GPIO output state (GPIOTxState)
+ //
+ GpioConfig->OutputState = ((PadCfgDwReg[0] & B_PCH_GPIO_TX_STATE) << (N_PCH_GPIO_TX_STATE + (N_GPIO_OUTPUT_BIT_POS + 1))) | (0x1 << N_GPIO_OUTPUT_BIT_POS);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ GpioConfig->OtherSettings = ((PadCfgDwReg[0] & B_PCH_GPIO_RX_RAW1) >> (N_PCH_GPIO_RX_RAW1 - (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1))) | (0x1 << N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS);
+
+ //
+ // Get GPIO Pad Mode (PMode)
+ //
+ GpioConfig->PadMode = ((PadCfgDwReg[0] & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS);
+
+ //
+ // Get GPIO termination (Term)
+ //
+ GpioConfig->ElectricalConfig = ((PadCfgDwReg[1] & B_PCH_GPIO_TERM) >> (N_PCH_GPIO_TERM - (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS);
+
+ //
+ // Get GPIO pad tolerance (padtol)
+ //
+ GpioConfig->ElectricalConfig |= ((PadCfgDwReg[1] & B_PCH_GPIO_PADTOL) >> (N_PCH_GPIO_PADTOL - (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS);
+}
+
+/**
+ This procedure will read multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[out] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadConfig (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_CONFIG *GpioData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadCfgDwReg[2];
+ UINT32 RegVal;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 PadBitPosition;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Read PADCFG DW0 register
+ //
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgDwReg[0]
+ );
+
+ //
+ // Read PADCFG DW1 register
+ //
+ GpioReadPadCfgReg (
+ GpioPad,
+ 1,
+ &PadCfgDwReg[1]
+ );
+
+ GpioConfigFromPadCfgRegValue (
+ GpioPad,
+ PadCfgDwReg,
+ GpioData
+ );
+
+ //
+ // Read HOSTSW_OWN registers
+ //
+ Status = GpioReadReg (
+ GpioHostOwnershipRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Host Software Ownership
+ //
+ GpioData->HostSoftPadOwn = (((RegVal >> PadBitPosition) & 0x1) << (N_GPIO_HOSTSW_OWN_BIT_POS + 1)) | (0x1 << N_GPIO_HOSTSW_OWN_BIT_POS);
+
+ //
+ // Read PADCFGLOCK register
+ //
+ Status = GpioReadReg (
+ GpioPadConfigLockRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Pad Configuration Lock state
+ //
+ GpioData->LockConfig = (((RegVal >> PadBitPosition) & 0x1) << 1) | 0x1;
+
+ //
+ // Read PADCFGLOCKTX register
+ //
+ Status = GpioReadReg (
+ GpioPadLockOutputRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Pad Configuration Lock Tx state
+ //
+ GpioData->LockConfig |= (((RegVal >> PadBitPosition) & 0x1) << 2) | 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioConfig GPIO Configuration data
+ @param[out] PadCfgDwReg PADCFG DWx register value
+ @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits to be modified
+
+ @retval Status
+**/
+EFI_STATUS
+GpioPadCfgRegValueFromGpioConfig (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadRstCfg;
+
+ //
+ // Configure Reset Type (PadRstCfg)
+ // Reset configuration depends on group type.
+ // This field requires support for new and deprecated settings.
+ //
+ Status = GpioPadRstCfgFromResetConfig (
+ GpioPad,
+ GpioConfig->PowerConfig,
+ &PadRstCfg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PadCfgDwRegMask[0] |= ((((GpioConfig->PowerConfig & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RST_CONF);
+ PadCfgDwReg[0] |= PadRstCfg << N_PCH_GPIO_RST_CONF;
+
+ //
+ // Configure how interrupt is triggered (RxEvCfg)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_LVL_EDG);
+ PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG);
+
+ //
+ // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE));
+ PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE);
+
+ //
+ // Configure GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> N_GPIO_DIRECTION_DIR_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS));
+ PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> (N_GPIO_DIRECTION_DIR_BIT_POS + 1)) << N_PCH_GPIO_TXDIS);
+
+ //
+ // Configure GPIO input inversion (RXINV)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> N_GPIO_DIRECTION_INV_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RXINV);
+ PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> (N_GPIO_DIRECTION_INV_BIT_POS + 1)) << N_PCH_GPIO_RXINV);
+
+ //
+ // Configure GPIO output state (GPIOTxState)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> N_GPIO_OUTPUT_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TX_STATE);
+ PadCfgDwReg[0] |= (((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> (N_GPIO_OUTPUT_BIT_POS + 1)) << N_PCH_GPIO_TX_STATE);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_RAW1);
+ PadCfgDwReg[0] |= (((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)) << N_PCH_GPIO_RX_RAW1);
+
+ //
+ // Configure GPIO Pad Mode (PMode)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> N_GPIO_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PAD_MODE);
+ PadCfgDwReg[0] |= (((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+
+ //
+ // Configure GPIO termination (Term)
+ //
+ PadCfgDwRegMask[1] |= ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TERM);
+ PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_PCH_GPIO_TERM);
+
+ //
+ // Configure GPIO pad tolerance (padtol)
+ //
+ PadCfgDwRegMask[1] |= ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PADTOL);
+ PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1)) << N_PCH_GPIO_PADTOL);
+
+ return Status;
+}
+
+/**
+ This procedure will configure multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_CONFIG *GpioData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadCfgDwReg[2];
+ UINT32 PadCfgDwRegMask[2];
+ UINT32 HostSoftOwnReg;
+ UINT32 HostSoftOwnRegMask;
+ UINT32 GpiGpeEnReg;
+ UINT32 GpiGpeEnRegMask;
+ UINT32 GpiNmiEnReg;
+ UINT32 GpiNmiEnRegMask;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 PadBitPosition;
+ UINT32 DwNum;
+
+ ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
+ ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get GPIO PADCFG register value from GPIO config data
+ //
+ GpioPadCfgRegValueFromGpioConfig (
+ GpioPad,
+ GpioData,
+ PadCfgDwReg,
+ PadCfgDwRegMask
+ );
+
+ //
+ // Write PADCFG DW0 register
+ //
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ ~PadCfgDwRegMask[0],
+ PadCfgDwReg[0]
+ );
+
+ //
+ // Write PADCFG DW1 register
+ //
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ ~PadCfgDwRegMask[1],
+ PadCfgDwReg[1]
+ );
+
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ HostSoftOwnRegMask = (GpioData->HostSoftPadOwn & 0x1) << PadBitPosition;
+ HostSoftOwnReg = (GpioData->HostSoftPadOwn >> 0x1) << PadBitPosition;
+
+ //
+ // Write HOSTSW_OWN registers
+ //
+ Status = GpioWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ ~HostSoftOwnRegMask,
+ HostSoftOwnReg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ GpiGpeEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
+ GpiGpeEnReg = ((GpioData->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition;
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ Status = GpioWriteReg (
+ GpioGpeEnableRegister,
+ Group,
+ DwNum,
+ ~GpiGpeEnRegMask,
+ GpiGpeEnReg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update value to be programmed in GPI_NMI_EN register
+ //
+ GpiNmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
+ GpiNmiEnReg = ((GpioData->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition;
+
+ Status = GpioWriteReg (
+ GpioNmiEnableRegister,
+ Group,
+ DwNum,
+ ~GpiNmiEnRegMask,
+ GpiNmiEnReg
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ if (GpiNmiEnReg == 0) {
+ //
+ // Not all GPIO have NMI capabilities. Since we always try to program this register,
+ // even when not enabling NMI for a pad so do not report such access as an error
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GroupIndex));
+ ASSERT (FALSE);
+ return Status;
+ }
+ }
+
+ //
+ // Program Pad Configuration Lock
+ //
+ if ((GpioData->LockConfig & GpioPadConfigLock) == GpioPadConfigLock) {
+ GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~0u,
+ 1 << PadBitPosition
+ );
+ }
+
+ //
+ // Program Pad Configuration Lock Tx
+ //
+ if ((GpioData->LockConfig & GpioOutputStateLock) == GpioOutputStateLock) {
+ GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~0u,
+ 1 << PadBitPosition
+ );
+ }
+ return Status;
+}
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ if (Value > 1) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_TX_STATE,
+ Value << N_PCH_GPIO_TX_STATE
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] OutputVal GPIO Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetOutputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *OutputVal
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgReg
+ );
+
+ *OutputVal = (PadCfgReg & B_PCH_GPIO_TX_STATE) >> N_PCH_GPIO_TX_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InpuHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InputVal
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgReg
+ );
+
+ *InputVal = (PadCfgReg & B_PCH_GPIO_RX_STATE) >> N_PCH_GPIO_RX_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO IOxAPIC interrupt number
+
+ @param[in] GpioPad GPIO pad
+ @param[out] IrqNum IRQ number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadIoApicIrqNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *IrqNum
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 1,
+ &PadCfgReg
+ );
+
+ *IrqNum = (PadCfgReg & B_PCH_GPIO_INTSEL) >> N_PCH_GPIO_INTSEL;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will configure GPIO input inversion
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIO input inversion
+ 0: No input inversion, 1: Invert input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ if (Value > 1) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_RXINV,
+ Value << N_PCH_GPIO_RXINV
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InvertState
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgReg
+ );
+
+ *InvertState = (PadCfgReg & B_PCH_GPIO_RXINV) >> N_PCH_GPIO_RXINV;
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO interrupt settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Level/Edge
+ use GPIO_INT_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadInterruptConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_INT_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RxLvlEdgeValue;
+ UINT32 IntRouteValue;
+ UINT32 PadNumber;
+ UINT32 GpeEnable;
+ UINT32 NmiEnable;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EFI_SUCCESS;
+
+ if (((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) != GpioHardwareDefault) {
+ RxLvlEdgeValue = ((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_RX_LVL_EDG,
+ RxLvlEdgeValue
+ );
+ }
+
+ if (((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) != GpioHardwareDefault) {
+
+ IntRouteValue = ((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~(B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE),
+ IntRouteValue
+ );
+
+ if ((Value & GpioIntSci) == GpioIntSci) {
+ GpeEnable = 0x1;
+ } else {
+ GpeEnable = 0x0;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioWriteReg (
+ GpioGpeEnableRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
+ GpeEnable << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Value & GpioIntNmi) == GpioIntNmi) {
+ NmiEnable = 0x1;
+ } else {
+ NmiEnable = 0x0;
+ }
+
+ Status = GpioWriteReg (
+ GpioNmiEnableRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
+ NmiEnable << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ if (NmiEnable == 0) {
+ //
+ // Not all GPIO have NMI capabilities. Since we always try to program this register,
+ // even when not enabling NMI for a pad so do not report such access as an error
+ //
+ return EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GpioGetGroupIndexFromGpioPad (GpioPad)));
+ }
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ This procedure will set GPIO electrical settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of termination
+ use GPIO_ELECTRICAL_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadElectricalConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_ELECTRICAL_CONFIG Value
+ )
+{
+ UINT32 TermValue;
+ UINT32 PadTolValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) != GpioHardwareDefault) {
+ TermValue = ((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_PCH_GPIO_TERM;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ (UINT32)~B_PCH_GPIO_TERM,
+ TermValue
+ );
+ }
+
+ if (((Value & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS) != GpioHardwareDefault) {
+ PadTolValue = ((Value & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1)) << N_PCH_GPIO_PADTOL;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ (UINT32)~B_PCH_GPIO_PADTOL,
+ PadTolValue
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for Pad Reset Configuration
+ use GPIO_RESET_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadRstCfg;
+
+ Status = EFI_SUCCESS;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((Value & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) != GpioHardwareDefault) {
+
+ //
+ // Reset configuration depends on group type.
+ // This field requires support for new and deprecated settings.
+ //
+ Status = GpioPadRstCfgFromResetConfig (
+ GpioPad,
+ Value,
+ &PadRstCfg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_RST_CONF,
+ PadRstCfg << N_PCH_GPIO_RST_CONF
+ );
+ }
+ return Status;
+}
+
+/**
+ This procedure will get GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Pad Reset Configuration
+ based on GPIO_RESET_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG *Value
+ )
+{
+ UINT32 PadRstCfg;
+ UINT32 PadCfgDw0Reg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgDw0Reg
+ );
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ PadRstCfg = (PadCfgDw0Reg & B_PCH_GPIO_RST_CONF) >> N_PCH_GPIO_RST_CONF;
+
+ *Value = GpioResetConfigFromPadRstCfg (
+ GpioPad,
+ PadRstCfg
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *HostSwRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioReadReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ HostSwRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 HostSwRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ 0,
+ HostSwRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadHostSwOwn Value of Host Software Pad Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadHostSwOwn
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+ UINT32 HostSwRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioReadReg (
+ GpioHostOwnershipRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &HostSwRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *PadHostSwOwn = (HostSwRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will set Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadHostSwOwn Pad Host Software Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadHostSwOwn
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioWriteReg (
+ GpioHostOwnershipRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~0u,
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get Gpio Pad Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadOwnVal Value of Pad Ownership
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadOwnership (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_OWN *PadOwnVal
+ )
+{
+ UINT32 Mask;
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 PadOwnRegValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Calculate RegOffset using Pad Ownership offset and GPIO Pad number.
+ // One DWord register contains information for 8 pads.
+ //
+ RegOffset = GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4;
+
+ //
+ // Calculate pad bit position within DWord register
+ //
+ PadNumber %= 8;
+ Mask = (BIT1 | BIT0) << (PadNumber * 4);
+
+ PadOwnRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+
+ *PadOwnVal = (GPIO_PAD_OWN) ((PadOwnRegValue & Mask) >> (PadNumber * 4));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will check state of Pad Config Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockRegVal Value of PadCfgLock register
+ Bit position - PadNumber
+ Bit value - 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioReadReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ PadCfgLockRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLock for selected pad
+ 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLock (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLock
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+ UINT32 PadCfgLockRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioReadReg (
+ GpioPadConfigLockRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &PadCfgLockRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *PadCfgLock = (PadCfgLockRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
+ Bit position - PadNumber
+ Bit value - 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockTxRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioReadReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ PadCfgLockTxRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLockTx for selected pad
+ 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLockTx (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLockTx
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+ UINT32 PadCfgLockTxRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioReadReg (
+ GpioPadLockOutputRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &PadCfgLockTxRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *PadCfgLockTx = (PadCfgLockTxRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnlock, 1: Unlock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlock
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~PadsToUnlock,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioUnlockPadCfgForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLock for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock Bitmask for pads which are going to be locked
+ Bit position - PadNumber
+ Bit value - 0: DoNotLock, 1: Lock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLock
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~0u,
+ PadsToLock
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioLockPadCfgForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlockTx
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~PadsToUnlockTx,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioUnlockPadCfgTxForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLockTx Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLockTx
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~0u,
+ PadsToLockTx
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioLockPadCfgTxForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+
+/**
+ This procedure will get Group to GPE mapping.
+
+ @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupToGpeDwX (
+ IN GPIO_GROUP *GroupToGpeDw0,
+ IN GPIO_GROUP *GroupToGpeDw1,
+ IN GPIO_GROUP *GroupToGpeDw2
+ )
+{
+ UINT32 Data32;
+ UINT32 PchPwrmBase;
+ GPIO_GROUP GpioGroupOffset;
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ Data32 = MmioRead32 ((UINTN) (PchPwrmBase + R_PCH_PWRM_GPIO_CFG));
+
+ *GroupToGpeDw0 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW0) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW0) + GpioGroupOffset;
+ *GroupToGpeDw1 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW1) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW1) + GpioGroupOffset;
+ *GroupToGpeDw2 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW2) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW2) + GpioGroupOffset;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set Group to GPE mapping.
+
+ @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGroupToGpeDwX (
+ IN GPIO_GROUP GroupToGpeDw0,
+ IN GPIO_GROUP GroupToGpeDw1,
+ IN GPIO_GROUP GroupToGpeDw2
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT32 PchPwrmBase;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if (((UINT32) GroupToGpeDw0 < GpioGroupLowest) || ((UINT32) GroupToGpeDw0 > GpioGroupHighest) ||
+ ((UINT32) GroupToGpeDw1 < GpioGroupLowest) || ((UINT32) GroupToGpeDw1 > GpioGroupHighest) ||
+ ((UINT32) GroupToGpeDw2 < GpioGroupLowest) || ((UINT32) GroupToGpeDw2 > GpioGroupHighest)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument exceeds GPIO group range\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if each group number is unique
+ //
+ if ((GroupToGpeDw0 == GroupToGpeDw1) ||
+ (GroupToGpeDw0 == GroupToGpeDw2) ||
+ (GroupToGpeDw1 == GroupToGpeDw2)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Values in GPE0_DWx registers are 0 based (GPP_A = 0h)
+ //
+ GroupToGpeDw0 = GpioGetGroupIndexFromGroup (GroupToGpeDw0);
+ GroupToGpeDw1 = GpioGetGroupIndexFromGroup (GroupToGpeDw1);
+ GroupToGpeDw2 = GpioGetGroupIndexFromGroup (GroupToGpeDw2);
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ //
+ // Program GPIO_CFG (PMRMBASE + 120h) register
+ //
+ Data32And = (UINT32) ~(B_PCH_PWRM_GPIO_CFG_GPE0_DW2 | B_PCH_PWRM_GPIO_CFG_GPE0_DW1 | B_PCH_PWRM_GPIO_CFG_GPE0_DW0);
+ Data32Or = (UINT32) ((GroupToGpeDw2 << N_PCH_PWRM_GPIO_CFG_GPE0_DW2) |
+ (GroupToGpeDw1 << N_PCH_PWRM_GPIO_CFG_GPE0_DW1) |
+ (GroupToGpeDw0 << N_PCH_PWRM_GPIO_CFG_GPE0_DW0));
+
+ MmioAndThenOr32 (
+ (PchPwrmBase + R_PCH_PWRM_GPIO_CFG),
+ Data32And,
+ Data32Or
+ );
+
+ Data32And = (UINT32) ~(B_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW0);
+ Data32Or = (UINT32) ((GroupToGpeDw2 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW2) |
+ (GroupToGpeDw1 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW1) |
+ (GroupToGpeDw0 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW0));
+ //
+ // Program MISCCFG register for Community 0
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM0, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 1
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM1, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 2
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM2, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 3
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM3, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPE number for provided GpioPad.
+ PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
+ what results in the fact that certain Pad can cause different General Purpose Event. Only three
+ GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
+ event (GPE_111 for 2-tier).
+
+ 1-tier:
+ Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
+ to determine what _LXX ACPI method would be called on event on selected GPIO pad
+
+ 2-tier:
+ Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
+ will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
+ what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
+ registers for all GPIO groups not mapped to 1-tier GPE.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeNumber GPE number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpeNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *GpeNumber
+ )
+{
+ GPIO_GROUP GroupToGpeDw0;
+ GPIO_GROUP GroupToGpeDw1;
+ GPIO_GROUP GroupToGpeDw2;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get GPIO groups mapping to 1-tier GPE
+ // This mapping is dependent on GPIO IP implementation
+ // and may change between chipset generations
+ //
+ GpioGetGroupToGpeDwX (&GroupToGpeDw0,&GroupToGpeDw1,&GroupToGpeDw2);
+
+ if (Group == GroupToGpeDw0) {
+ *GpeNumber = PadNumber;
+ } else if (Group == GroupToGpeDw1) {
+ *GpeNumber = PadNumber + 32;
+ } else if (Group == GroupToGpeDw2) {
+ *GpeNumber = PadNumber + 64;
+ } else {
+ //
+ // If Group number doesn't match any of above then
+ // it means than certain pad is routed to 2-tier GPE
+ // which all are under GPE_111 (0x6F)
+ //
+ *GpeNumber = PCH_GPIO_2_TIER_MASTER_GPE_NUMBER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Clear GPI SMI Status bit by writing '1'
+ //
+ Status = GpioWriteReg (
+ GpioSmiStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ (UINT32) (BIT0 << PadBitPosition)
+ );
+
+ return Status;
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ )
+{
+ UINT32 DwNum;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ //
+ // Disable all GPI SMI
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
+ GpioWriteReg (
+ GpioSmiStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ 0xFFFFFFFF
+ );
+ }
+ }
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This procedure is used to disable all GPI SMI
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioDisableAllGpiSmi (
+ VOID
+ )
+{
+ UINT32 DwNum;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ //
+ // Disable all GPI SMI
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
+ GpioWriteReg (
+ GpioSmiEnableRegister,
+ Group,
+ DwNum,
+ 0u,
+ 0u
+ );
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN GPIO_PAD GpioPad,
+ OUT UINTN *GpiNum
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 Index;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ *GpiNum = 0;
+
+ for (Index = 0; Index < GroupIndex; Index++) {
+ *GpiNum += (UINTN) (GpioGroupInfo[Index].PadPerGroup);
+ }
+ *GpiNum += (UINTN) PadNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
+
+ @param[in] GpioPad GPIO pad
+
+ @retval Data 0 means 1-tier, 1 means 2-tier
+**/
+BOOLEAN
+GpioCheckFor2Tier (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 Data32;
+
+ GpioGetGpeNumber (GpioPad, &Data32);
+ if (Data32 == PCH_GPIO_2_TIER_MASTER_GPE_NUMBER) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This procedure is used to clear GPE STS for a specified GpioPad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiGpeSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for 2-tier
+ //
+ if (!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Clear GPI GPE Status bit by writing '1'
+ //
+ Status = GpioWriteReg (
+ GpioGpeStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ (UINT32) (BIT0 << PadBitPosition)
+ );
+
+ return Status;
+}
+
+/**
+ This procedure is used to read GPE STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] Data GPE STS data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiGpeSts (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *Data
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GpeStsRegVal;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for 2-tier
+ //
+ if (!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Read GPI GPE Status bits
+ //
+ Status = GpioReadReg (
+ GpioGpeStatusRegister,
+ Group,
+ DwNum,
+ &GpeStsRegVal
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Data = (GpeStsRegVal >> PadBitPosition) & 0x1;
+
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h
new file mode 100644
index 0000000000..97a5287067
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h
@@ -0,0 +1,327 @@
+/** @file
+ Header file for GPIO Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GPIO_LIBRARY_H_
+#define _GPIO_LIBRARY_H_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <GpioPinsSklLp.h>
+#include <GpioPinsSklH.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchSbiAccessLib.h>
+
+typedef struct {
+ GPIO_PAD Pad;
+ GPIO_PAD_MODE Mode;
+} GPIO_PAD_NATIVE_FUNCTION;
+
+
+// BIT15-0 - pad number
+// BIT31-16 - group info
+// BIT23- 16 - group index
+// BIT31- 24 - chipset ID
+#define PAD_INFO_MASK 0x0000FFFF
+#define GROUP_INFO_POSITION 16
+#define GROUP_INFO_MASK 0xFFFF0000
+#define GROUP_INDEX_MASK 0x00FF0000
+#define UNIQUE_ID_MASK 0xFF000000
+#define UNIQUE_ID_POSITION 24
+
+#define GPIO_PAD_DEF(Group,Pad) (UINT32)(((Group) << 16) + (Pad))
+#define GPIO_GROUP_DEF(Index,ChipsetId) ((Index) | ((ChipsetId) << 8))
+#define GPIO_GET_GROUP_INDEX(Group) ((Group) & 0xFF)
+#define GPIO_GET_GROUP_FROM_PAD(Pad) ((Pad) >> 16)
+#define GPIO_GET_GROUP_INDEX_FROM_PAD(Pad) GPIO_GET_GROUP_INDEX (((Pad) >> 16))
+#define GPIO_GET_PAD_NUMBER(Pad) ((Pad) & 0xFFFF)
+#define GPIO_GET_CHIPSET_ID(Pad) ((Pad) >> 24)
+
+#define GPIO_GET_PAD_POSITION(PadNumber) ((PadNumber) % 32)
+#define GPIO_GET_DW_NUM(PadNumber) ((PadNumber) / 32)
+
+//
+// Unique ID used in GpioPad defines
+//
+#define GPIO_SKL_H_CHIPSET_ID 0x1
+#define GPIO_SKL_LP_CHIPSET_ID 0x2
+
+//
+// Below defines are based on GPIO_CONFIG structure fields
+//
+#define B_GPIO_PAD_MODE_MASK 0xF
+#define N_GPIO_PAD_MODE_BIT_POS 0
+#define B_GPIO_HOSTSW_OWN_MASK 0x3
+#define N_GPIO_HOSTSW_OWN_BIT_POS 0
+#define B_GPIO_DIRECTION_MASK 0x1F
+#define B_GPIO_DIRECTION_DIR_MASK 0x7
+#define N_GPIO_DIRECTION_DIR_BIT_POS 0
+#define B_GPIO_DIRECTION_INV_MASK 0x18
+#define N_GPIO_DIRECTION_INV_BIT_POS 3
+#define B_GPIO_OUTPUT_MASK 0x3
+#define N_GPIO_OUTPUT_BIT_POS 0
+#define N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS 0
+#define N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS 5
+#define B_GPIO_RESET_CONFIG_RESET_MASK 0x3F
+#define N_GPIO_RESET_CONFIG_OLD_RESET_TYPE BIT1
+#define B_GPIO_RESET_CONFIG_OLD_RESET_MASK 0xF
+#define N_GPIO_RESET_CONFIG_RESET_BIT_POS 0
+#define B_GPIO_RESET_CONFIG_GPD_RESET_MASK (BIT5 | BIT4)
+#define B_GPIO_RESET_CONFIG_GPP_RESET_MASK (BIT3 | BIT2)
+#define N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS 0
+#define N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS 5
+#define N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS 0
+
+//
+// Structure for storing information about registers offset, community,
+// maximal pad number for available groups
+//
+typedef struct {
+ PCH_SBI_PID Community;
+ UINT32 PadOwnOffset;
+ UINT32 HostOwnOffset;
+ UINT32 GpiIsOffset;
+ UINT32 GpiIeOffset;
+ UINT32 GpiGpeStsOffset;
+ UINT32 GpiGpeEnOffset;
+ UINT32 SmiStsOffset;
+ UINT32 SmiEnOffset;
+ UINT32 NmiStsOffset;
+ UINT32 NmiEnOffset;
+ UINT32 PadCfgLockOffset;
+ UINT32 PadCfgLockTxOffset;
+ UINT32 PadCfgOffset;
+ UINT32 PadPerGroup;
+} GPIO_GROUP_INFO;
+
+//
+// If in GPIO_GROUP_INFO structure certain register doesn't exist
+// it will have value equal to NO_REGISTER_FOR_PROPERTY
+//
+#define NO_REGISTER_FOR_PROPERTY (~0u)
+
+//
+// PADCFG register is split into multiple DW registers
+// PAD_CFG_SIZE holds number of bytes used by all those registers for one pad
+//
+#define PAD_CFG_SIZE 0x08
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ );
+
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINTN *GpioGroupInfoTableLength
+ );
+
+/**
+ This procedure will check if GpioPad is owned by host.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is owned by host
+ @retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadHostOwned (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will check if GpioPad argument is valid.
+ Function will check below conditions:
+ - GpioPad represents a pad for current PCH
+ - GpioPad belongs to valid GpioGroup
+ - GPIO PadNumber is not greater than number of pads for this group
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is valid and can be used with GPIO lib API
+ @retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadValid (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[out] PadCfgRegValue Read data
+
+ @retval none
+**/
+VOID
+GpioReadPadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ OUT UINT32 *PadCfgRegValue
+ );
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
+ @param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
+
+ @retval none
+**/
+VOID
+GpioWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 PadCfgAndMask,
+ IN UINT32 PadCfgOrMask
+ );
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+SetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ );
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ );
+
+/**
+ This function checks if GPIO pin is a GSPI chip select pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsGpioPadAGSpiCsbPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ );
+
+/**
+ This function checks if GPIO pin is a SataDevSlp pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsPadASataDevSlpPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ );
+
+/**
+ This internal procedure will calculate GPIO_RESET_CONFIG value (new type)
+ based on provided PadRstCfg for a specific GPIO Pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadRstCfg GPIO PadRstCfg value
+
+ @retval GpioResetConfig GPIO Reset configuration (new type)
+**/
+GPIO_RESET_CONFIG
+GpioResetConfigFromPadRstCfg (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadRstCfg
+ );
+
+/**
+ This internal procedure will calculate PadRstCfg register value based
+ on provided GPIO Reset configuration for a certain pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioResetConfig GPIO Reset configuration
+ @param[out] PadRstCfg GPIO PadRstCfg value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid configuration
+**/
+EFI_STATUS
+GpioPadRstCfgFromResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG GpioResetConfig,
+ OUT UINT32 *PadRstCfg
+ );
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioConfig GPIO Configuration data
+ @param[out] PadCfgDwReg PADCFG DWx register value
+ @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits to be modified
+
+ @retval Status
+**/
+EFI_STATUS
+GpioPadCfgRegValueFromGpioConfig (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ );
+#endif // _GPIO_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
new file mode 100644
index 0000000000..e57e3ecbfa
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
@@ -0,0 +1,685 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific usage
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "GpioLibrary.h"
+
+//
+// Chipset specific data
+//
+//SerialIo
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpI2cGpio[PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHI2cGpio[PCH_H_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpUartGpio[PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHUartGpio[PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpSpiGpio[PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSpiGpio[PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+
+//SATA
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpSataPortResetToGpioMap[PCH_LP_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpSataDevSlpPinToGpioMap[PCH_LP_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS];
+
+//
+// SKL specific
+//
+extern GPIO_GROUP_INFO mPchLpGpioGroupInfo[V_PCH_LP_GPIO_GROUP_MAX];
+extern GPIO_GROUP_INFO mPchHGpioGroupInfo[V_PCH_H_GPIO_GROUP_MAX];
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+SetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ )
+{
+ UINT32 PadCfgOrMask;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (PadModeValue != (GPIO_PAD_MODE)GpioHardwareDefault) {
+
+ PadCfgOrMask = (((PadModeValue & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_PAD_MODE,
+ PadCfgOrMask
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ )
+{
+ UINT32 PadCfgRegValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgRegValue
+ );
+
+ *PadModeValue = (GPIO_PAD_MODE)(((PadCfgRegValue & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINTN *GpioGroupInfoTableLength
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ *GpioGroupInfoTableLength = sizeof (mPchLpGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mPchLpGpioGroupInfo;
+ } else {
+ *GpioGroupInfoTableLength = sizeof (mPchHGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mPchHGpioGroupInfo;
+ }
+}
+
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if ((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID (GpioPad) == GPIO_SKL_H_CHIPSET_ID)) {
+ return TRUE;
+ } else if ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID (GpioPad) == GPIO_SKL_LP_CHIPSET_ID)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ This procedure will get number of pads for certain GPIO group
+
+ @param[in] Group GPIO group number
+
+ @retval Value Pad number for group
+ If illegal group number then return 0
+**/
+UINT32
+GpioGetPadPerGroup (
+ IN GPIO_GROUP Group
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return 0;
+ } else {
+ return GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+}
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT8
+GpioGetNumberOfGroups (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return V_PCH_LP_GPIO_GROUP_MAX;
+ } else {
+ return V_PCH_H_GPIO_GROUP_MAX;
+ }
+}
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return (UINT32) GPIO_SKL_LP_GROUP_GPP_A;
+ } else {
+ return (UINT32) GPIO_SKL_H_GROUP_GPP_A;
+ }
+}
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return (UINT32) GPIO_SKL_LP_GROUP_GPD;
+ } else {
+ return (UINT32) GPIO_SKL_H_GROUP_GPD;
+ }
+}
+
+/**
+ This procedure will get group number
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group number
+**/
+GPIO_GROUP
+GpioGetGroupFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return GPIO_GET_GROUP_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based)
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32) GPIO_GET_GROUP_INDEX_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup Gpio Group
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ )
+{
+ return (UINT32) GPIO_GET_GROUP_INDEX (GpioGroup);
+}
+
+/**
+ This procedure will get pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32) GPIO_GET_PAD_NUMBER (GpioPad);
+}
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return GPIO_PAD_DEF (Group,PadNumber);
+ } else {
+ return GPIO_PAD_DEF (Group,PadNumber);
+ }
+}
+
+/**
+ This procedure will return GpioPad from GroupIndex and PadNumber
+
+ @param[in] GroupIndex GPIO GroupIndex
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupIndexAndPadNumber (
+ IN UINT32 GroupIndex,
+ IN UINT32 PadNumber
+ )
+{
+ GPIO_GROUP Group;
+
+ if (GetPchSeries () == PchLp) {
+ Group = GPIO_GROUP_DEF (GroupIndex, GPIO_SKL_LP_CHIPSET_ID);
+ return GPIO_PAD_DEF (Group,PadNumber);
+ } else {
+ Group = GPIO_GROUP_DEF (GroupIndex, GPIO_SKL_H_CHIPSET_ID);
+ return GPIO_PAD_DEF (Group,PadNumber);
+ }
+}
+
+
+/**
+ This function sets SerialIo I2C controller pins into native mode
+
+ @param[in] SerialIoI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2cPinsIntoNativeMode (
+ IN UINT32 SerialIoI2cControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SerialIoI2cControllerNumber < PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchLpI2cGpio;
+ } else {
+ ASSERT (SerialIoI2cControllerNumber < PCH_H_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchHI2cGpio;
+ }
+
+ for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, I2cGpio[SerialIoI2cControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, 0);
+ }
+ return Status;
+}
+
+/**
+ This function sets SerialIo I2C controller pins tolerance
+
+ @param[in] SerialIoI2CControllerNumber I2C controller
+ @param[in] Pad1v8Tolerance TRUE: Enable 1v8 Pad tolerance
+ FALSE: Disable 1v8 Pad tolerance
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2CPinsTolerance (
+ IN UINT32 SerialIoI2cControllerNumber,
+ IN BOOLEAN Pad1v8Tolerance
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+ GPIO_CONFIG GpioData;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SerialIoI2cControllerNumber < PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchLpI2cGpio;
+ } else {
+ ASSERT (SerialIoI2cControllerNumber < PCH_H_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchHI2cGpio;
+ }
+
+ ZeroMem (&GpioData, sizeof (GPIO_CONFIG));
+ if (Pad1v8Tolerance) {
+ GpioData.ElectricalConfig = GpioTolerance1v8;
+ } else {
+ GpioData.ElectricalConfig = GpioNoTolerance1v8;
+ }
+ for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++) {
+ GpioGetPadOwnership (I2cGpio[SerialIoI2cControllerNumber][Index].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ Status = GpioSetPadConfig (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, &GpioData);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+
+/**
+ This function sets SerialIo UART controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber UART controller
+ @param[in] HardwareFlowControl Hardware Flow control
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoUartPinsIntoNativeMode (
+ IN UINT32 SerialIoUartControllerNumber,
+ IN BOOLEAN HardwareFlowControl
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN PinsUsed;
+ GPIO_PAD_NATIVE_FUNCTION (*UartGpio) [PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ ASSERT (SerialIoUartControllerNumber < PCH_SERIALIO_MAX_UART_CONTROLLERS);
+
+ if (GetPchSeries () == PchLp) {
+ UartGpio = mPchLpUartGpio;
+ } else {
+ UartGpio = mPchHUartGpio;
+ }
+
+ if (HardwareFlowControl) {
+ PinsUsed = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER;
+ } else {
+ PinsUsed = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL;
+ }
+
+ for (Index = 0; Index < PinsUsed; Index++) {
+ Status = SetGpioPadMode (UartGpio[SerialIoUartControllerNumber][Index].Pad, UartGpio[SerialIoUartControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (UartGpio[SerialIoUartControllerNumber][Index].Pad, 0);
+ }
+ return Status;
+}
+
+/**
+ This function sets SerialIo SPI controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber SPI controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoSpiPinsIntoNativeMode (
+ IN UINT32 SerialIoSpiControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*SpiGpio) [PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ ASSERT (SerialIoSpiControllerNumber < PCH_SERIALIO_MAX_SPI_CONTROLLERS);
+
+ if (GetPchSeries () == PchLp) {
+ SpiGpio = mPchLpSpiGpio;
+ } else {
+ SpiGpio = mPchHSpiGpio;
+ }
+
+ for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (SpiGpio[SerialIoSpiControllerNumber][Index].Pad, SpiGpio[SerialIoSpiControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (SpiGpio[SerialIoSpiControllerNumber][Index].Pad, 0);
+ }
+ return Status;
+}
+
+
+/**
+ This function checks if GPIO pin is a GSPI chip select pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsGpioPadAGSpiCsbPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ )
+{
+ UINT32 ControllerMax;
+ UINT32 ControllerIndex;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION (*SpiGpio) [PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+
+ if (GetPchSeries () == PchLp) {
+ SpiGpio = mPchLpSpiGpio;
+ ControllerMax = sizeof (mPchLpSpiGpio) / sizeof (GPIO_PAD_NATIVE_FUNCTION) / PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER;
+ } else {
+ SpiGpio = mPchHSpiGpio;
+ ControllerMax = sizeof (mPchHSpiGpio) / sizeof (GPIO_PAD_NATIVE_FUNCTION) / PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER;
+ }
+
+ for (ControllerIndex = 0; ControllerIndex < ControllerMax; ControllerIndex++) {
+ if ((GpioPad == SpiGpio[ControllerIndex][0].Pad) &&
+ (PadMode == SpiGpio[ControllerIndex][0].Mode)) {
+ GpioGetPadOwnership (SpiGpio[ControllerIndex][0].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ This function checks if GPIO pin for SATA reset port is in GPIO MODE
+
+ @param[in] SataPort SATA port number
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsSataResetPortInGpioMode (
+ IN UINTN SataPort
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GpioPin;
+ GPIO_PAD_MODE GpioMode;
+
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SataPort < PCH_LP_AHCI_MAX_PORTS);
+ GpioPin = mPchLpSataPortResetToGpioMap[SataPort].Pad;
+ } else {
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ GpioPin = mPchHSataPortResetToGpioMap[SataPort].Pad;
+ }
+
+ Status = GetGpioPadMode (GpioPin, &GpioMode);
+ if ((EFI_ERROR (Status)) || (GpioMode != GpioPadModeGpio)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ This function checks if GPIO pin is a SataDevSlp pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsPadASataDevSlpPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ )
+{
+ UINT32 SataDevSlpPinMax;
+ UINT32 SataDevSlpPinIndex;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION *SataDevSlpPinToGpioMap;
+
+ if (GetPchSeries () == PchLp) {
+ SataDevSlpPinToGpioMap = mPchLpSataDevSlpPinToGpioMap;
+ SataDevSlpPinMax = sizeof (mPchLpSataDevSlpPinToGpioMap) /sizeof (GPIO_PAD_NATIVE_FUNCTION);
+ } else {
+ SataDevSlpPinToGpioMap = mPchHSataDevSlpPinToGpioMap;
+ SataDevSlpPinMax = sizeof (mPchHSataDevSlpPinToGpioMap) /sizeof (GPIO_PAD_NATIVE_FUNCTION);
+ }
+
+ for (SataDevSlpPinIndex = 0; SataDevSlpPinIndex < SataDevSlpPinMax; SataDevSlpPinIndex++) {
+ if ((GpioPad == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad) &&
+ (PadMode == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Mode)) {
+ GpioGetPadOwnership (SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad
+ )
+{
+ GPIO_PAD_MODE DevSlpPadMode;
+ GPIO_PAD DevSlpGpioPad;
+ GPIO_PAD_MODE GpioMode;
+ EFI_STATUS Status;
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SataPort < PCH_LP_AHCI_MAX_PORTS);
+ DevSlpGpioPad = mPchLpSataDevSlpPinToGpioMap[SataPort].Pad;
+ DevSlpPadMode = mPchLpSataDevSlpPinToGpioMap[SataPort].Mode;
+ } else {
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ DevSlpGpioPad = mPchHSataDevSlpPinToGpioMap[SataPort].Pad;
+ DevSlpPadMode = mPchHSataDevSlpPinToGpioMap[SataPort].Mode;
+ }
+
+ Status = GetGpioPadMode (DevSlpGpioPad, &GpioMode);
+
+ if (EFI_ERROR (Status) || (GpioMode != DevSlpPadMode)) {
+ *DevSlpPad = 0x0;
+ return FALSE;
+ } else {
+ *DevSlpPad = DevSlpGpioPad;
+ return TRUE;
+ }
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c
new file mode 100644
index 0000000000..c36792139c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c
@@ -0,0 +1,190 @@
+/** @file
+ This file contains SKL specific GPIO information
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "GpioLibrary.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchLpGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_PCH_LP_PCR_GPIO_GPP_A_PAD_OWN, R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_A_GPI_IS, R_PCH_PCR_GPIO_GPP_A_GPI_IE, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_A_SMI_STS, R_PCH_PCR_GPIO_GPP_A_SMI_EN, R_PCH_PCR_GPIO_GPP_A_NMI_STS, R_PCH_PCR_GPIO_GPP_A_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET, V_PCH_GPIO_GPP_A_PAD_MAX}, //SKL PCH-LP GPP_A
+ {PID_GPIOCOM0, R_PCH_LP_PCR_GPIO_GPP_B_PAD_OWN, R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_B_GPI_IS, R_PCH_PCR_GPIO_GPP_B_GPI_IE, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_B_SMI_STS, R_PCH_PCR_GPIO_GPP_B_SMI_EN, R_PCH_PCR_GPIO_GPP_B_NMI_STS, R_PCH_PCR_GPIO_GPP_B_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET, V_PCH_GPIO_GPP_B_PAD_MAX}, //SKL PCH-LP GPP_B
+ {PID_GPIOCOM1, R_PCH_LP_PCR_GPIO_GPP_C_PAD_OWN, R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_C_GPI_IS, R_PCH_PCR_GPIO_GPP_C_GPI_IE, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_C_SMI_STS, R_PCH_PCR_GPIO_GPP_C_SMI_EN, R_PCH_PCR_GPIO_GPP_C_NMI_STS, R_PCH_PCR_GPIO_GPP_C_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET, V_PCH_GPIO_GPP_C_PAD_MAX}, //SKL PCH-LP GPP_C
+ {PID_GPIOCOM1, R_PCH_LP_PCR_GPIO_GPP_D_PAD_OWN, R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_D_GPI_IS, R_PCH_PCR_GPIO_GPP_D_GPI_IE, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_D_SMI_STS, R_PCH_PCR_GPIO_GPP_D_SMI_EN, R_PCH_PCR_GPIO_GPP_D_NMI_STS, R_PCH_PCR_GPIO_GPP_D_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET, V_PCH_GPIO_GPP_D_PAD_MAX}, //SKL PCH-LP GPP_D
+ {PID_GPIOCOM1, R_PCH_LP_PCR_GPIO_GPP_E_PAD_OWN, R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_E_GPI_IS, R_PCH_PCR_GPIO_GPP_E_GPI_IE, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_E_SMI_STS, R_PCH_PCR_GPIO_GPP_E_SMI_EN, R_PCH_PCR_GPIO_GPP_E_NMI_STS, R_PCH_PCR_GPIO_GPP_E_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET, V_PCH_LP_GPIO_GPP_E_PAD_MAX}, //SKL PCH-LP GPP_E
+ {PID_GPIOCOM3, R_PCH_LP_PCR_GPIO_GPP_F_PAD_OWN, R_PCH_LP_PCR_GPIO_GPP_F_HOSTSW_OWN, R_PCH_LP_PCR_GPIO_GPP_F_GPI_IS, R_PCH_LP_PCR_GPIO_GPP_F_GPI_IE, R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_STS,R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX, R_PCH_LP_PCR_GPIO_GPP_F_PADCFG_OFFSET, V_PCH_GPIO_GPP_F_PAD_MAX}, //SKL PCH-LP GPP_F
+ {PID_GPIOCOM3, R_PCH_LP_PCR_GPIO_GPP_G_PAD_OWN, R_PCH_LP_PCR_GPIO_GPP_G_HOSTSW_OWN, R_PCH_LP_PCR_GPIO_GPP_G_GPI_IS, R_PCH_LP_PCR_GPIO_GPP_G_GPI_IE, R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_STS,R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX, R_PCH_LP_PCR_GPIO_GPP_G_PADCFG_OFFSET, V_PCH_LP_GPIO_GPP_G_PAD_MAX}, //SKL PCH-LP GPP_G
+ {PID_GPIOCOM2, R_PCH_LP_PCR_GPIO_GPD_PAD_OWN, R_PCH_PCR_GPIO_GPD_HOSTSW_OWN, R_PCH_PCR_GPIO_GPD_GPI_IS, R_PCH_PCR_GPIO_GPD_GPI_IE, R_PCH_PCR_GPIO_GPD_GPI_GPE_STS, R_PCH_PCR_GPIO_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET, V_PCH_GPIO_GPD_PAD_MAX}, //SKL PCH-LP GPD
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchHGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_PCH_H_PCR_GPIO_GPP_A_PAD_OWN, R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_A_GPI_IS, R_PCH_PCR_GPIO_GPP_A_GPI_IE, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_A_SMI_STS, R_PCH_PCR_GPIO_GPP_A_SMI_EN, R_PCH_PCR_GPIO_GPP_A_NMI_STS, R_PCH_PCR_GPIO_GPP_A_NMI_EN, R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET, V_PCH_GPIO_GPP_A_PAD_MAX}, //SKL PCH-H GPP_A
+ {PID_GPIOCOM0, R_PCH_H_PCR_GPIO_GPP_B_PAD_OWN, R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_B_GPI_IS, R_PCH_PCR_GPIO_GPP_B_GPI_IE, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_B_SMI_STS, R_PCH_PCR_GPIO_GPP_B_SMI_EN, R_PCH_PCR_GPIO_GPP_B_NMI_STS, R_PCH_PCR_GPIO_GPP_B_NMI_EN, R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET, V_PCH_GPIO_GPP_B_PAD_MAX}, //SKL PCH-H GPP_B
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_C_PAD_OWN, R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_C_GPI_IS, R_PCH_PCR_GPIO_GPP_C_GPI_IE, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_C_SMI_STS, R_PCH_PCR_GPIO_GPP_C_SMI_EN, R_PCH_PCR_GPIO_GPP_C_NMI_STS, R_PCH_PCR_GPIO_GPP_C_NMI_EN, R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET, V_PCH_GPIO_GPP_C_PAD_MAX}, //SKL PCH-H GPP_C
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_D_PAD_OWN, R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_D_GPI_IS, R_PCH_PCR_GPIO_GPP_D_GPI_IE, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_D_SMI_STS, R_PCH_PCR_GPIO_GPP_D_SMI_EN, R_PCH_PCR_GPIO_GPP_D_NMI_STS, R_PCH_PCR_GPIO_GPP_D_NMI_EN, R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET, V_PCH_GPIO_GPP_D_PAD_MAX}, //SKL PCH-H GPP_D
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_E_PAD_OWN, R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_E_GPI_IS, R_PCH_PCR_GPIO_GPP_E_GPI_IE, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_E_SMI_STS, R_PCH_PCR_GPIO_GPP_E_SMI_EN, R_PCH_PCR_GPIO_GPP_E_NMI_STS, R_PCH_PCR_GPIO_GPP_E_NMI_EN, R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_E_PAD_MAX}, //SKL PCH-H GPP_E
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_F_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_F_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_F_GPI_IS, R_PCH_H_PCR_GPIO_GPP_F_GPI_IE, R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_F_SMI_STS,R_PCH_H_PCR_GPIO_GPP_F_SMI_EN, R_PCH_H_PCR_GPIO_GPP_F_NMI_STS,R_PCH_H_PCR_GPIO_GPP_F_NMI_EN, R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_F_PADCFG_OFFSET, V_PCH_GPIO_GPP_F_PAD_MAX}, //SKL PCH-H GPP_F
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_G_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_G_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_G_GPI_IS, R_PCH_H_PCR_GPIO_GPP_G_GPI_IE, R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_G_SMI_STS,R_PCH_H_PCR_GPIO_GPP_G_SMI_EN, R_PCH_H_PCR_GPIO_GPP_G_NMI_STS,R_PCH_H_PCR_GPIO_GPP_G_NMI_EN, R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_G_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_G_PAD_MAX}, //SKL PCH-H GPP_G
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_H_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_H_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_H_GPI_IS, R_PCH_H_PCR_GPIO_GPP_H_GPI_IE, R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_H_SMI_STS,R_PCH_H_PCR_GPIO_GPP_H_SMI_EN, R_PCH_H_PCR_GPIO_GPP_H_NMI_STS,R_PCH_H_PCR_GPIO_GPP_H_NMI_EN, R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_H_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_H_PAD_MAX}, //SKL PCH-H GPP_H
+ {PID_GPIOCOM3, R_PCH_H_PCR_GPIO_GPP_I_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_I_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_I_GPI_IS, R_PCH_H_PCR_GPIO_GPP_I_GPI_IE, R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_I_SMI_STS,R_PCH_H_PCR_GPIO_GPP_I_SMI_EN, R_PCH_H_PCR_GPIO_GPP_I_NMI_STS,R_PCH_H_PCR_GPIO_GPP_I_NMI_EN, R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_I_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_I_PAD_MAX}, //SKL PCH-H GPP_I
+ {PID_GPIOCOM2, R_PCH_H_PCR_GPIO_GPD_PAD_OWN, R_PCH_PCR_GPIO_GPD_HOSTSW_OWN, R_PCH_PCR_GPIO_GPD_GPI_IS, R_PCH_PCR_GPIO_GPD_GPI_IE, R_PCH_PCR_GPIO_GPD_GPI_GPE_STS, R_PCH_PCR_GPIO_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET, V_PCH_GPIO_GPD_PAD_MAX} //SKL PCH-H GPD
+};
+
+//
+// I2C controller pins
+// I2C[controller number][pin: SDA/SCL]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpI2cGpio [PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=
+{
+ {{GPIO_SKL_LP_GPP_C16, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_C17, GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_C18, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_C19, GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F4, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F5 , GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F6, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F7 , GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F8, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F9 , GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F10, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F11, GpioPadModeNative1}}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHI2cGpio [PCH_H_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=
+{
+ {{GPIO_SKL_H_GPP_C16, GpioPadModeNative1}, {GPIO_SKL_H_GPP_C17, GpioPadModeNative1}}, //I2C0
+ {{GPIO_SKL_H_GPP_C18, GpioPadModeNative1}, {GPIO_SKL_H_GPP_C19, GpioPadModeNative1}}, //I2C1
+ {{GPIO_SKL_H_GPP_D13, GpioPadModeNative3}, {GPIO_SKL_H_GPP_D14, GpioPadModeNative3}}, //I2C2
+ {{GPIO_SKL_H_GPP_D4, GpioPadModeNative2}, {GPIO_SKL_H_GPP_D23, GpioPadModeNative2}} //I2C3
+};
+
+//
+// UART controller pins
+// UART[controller number][pin: RXD/TXD/RTSB/CTSB]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpUartGpio [PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER]=
+{
+ { // UART0
+ {GPIO_SKL_LP_GPP_C8, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C9, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C10, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C11, GpioPadModeNative1}
+ },
+ { // UART1
+ {GPIO_SKL_LP_GPP_C12, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C13, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C14, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C15, GpioPadModeNative1}
+ },
+ { // UART2
+ {GPIO_SKL_LP_GPP_C20, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C21, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C22, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C23, GpioPadModeNative1}
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHUartGpio [PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER]=
+{
+ { // UART0
+ {GPIO_SKL_H_GPP_C8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C9, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C10, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C11, GpioPadModeNative1}
+ },
+ { // UART1
+ {GPIO_SKL_H_GPP_C12, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C13, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C14, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C15, GpioPadModeNative1}
+ },
+ { // UART2
+ {GPIO_SKL_H_GPP_C20, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C21, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C22, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C23, GpioPadModeNative1}
+ }
+};
+
+//
+// SPI controller pins
+// SPI[controller number][pin: CSB/CLK/MISO/MOSI]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSpiGpio [PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER]=
+{
+ { // SPI0
+ {GPIO_SKL_LP_GPP_B15, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B16, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B17, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B18, GpioPadModeNative1}
+ },
+ { // SPI1
+ {GPIO_SKL_LP_GPP_B19, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B20, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B21, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B22, GpioPadModeNative1}
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSpiGpio [PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER]=
+{
+ { // SPI0
+ {GPIO_SKL_H_GPP_B15, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B16, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B17, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B18, GpioPadModeNative1}
+ },
+ { // SPI1
+ {GPIO_SKL_H_GPP_B19, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B20, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B21, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B22, GpioPadModeNative1}
+ }
+};
+
+//
+// SATA reset port to GPIO pin mapping
+// SATAGP_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataPortResetToGpioMap[PCH_LP_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_LP_GPP_E0, GpioPadModeNative2},
+ {GPIO_SKL_LP_GPP_E1, GpioPadModeNative2},
+ {GPIO_SKL_LP_GPP_E2, GpioPadModeNative2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_H_GPP_E0, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_E1, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_E2, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F0, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F1, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F2, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F3, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F4, GpioPadModeNative2}
+};
+
+//
+// SATADevSlpPin to GPIO pin mapping
+// SATA_DEVSLP_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataDevSlpPinToGpioMap[PCH_LP_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_LP_GPP_E4, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_E5, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_E6, GpioPadModeNative1}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_H_GPP_E4, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_E5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_E6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F9, GpioPadModeNative1}
+};
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
new file mode 100644
index 0000000000..747fa67199
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Component description file for the PeiDxeSmmGpioLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmGpioLib
+FILE_GUID = 16EC5CA8-8195-4847-B6CB-662BD7B763F2
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchCycleDecodingLib
+PchSbiAccessLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+GpioLib.c
+GpioLibrary.h
+GpioNativeLib.c
+GpioInit.c
+PchSklGpioData.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
new file mode 100644
index 0000000000..68b0b5dd4b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
@@ -0,0 +1,1137 @@
+/** @file
+ PCH cycle deocding configuration and query library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchCycleDecodingLib.h>
+
+/**
+ Set PCH ACPI base address.
+ The Address should not be 0 and should be 256 bytes alignment, and it is IO space, so must not exceed 0xFFFF.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [7] to diable ACPI base address first before changing base address.
+ 2. program PMC PCI offset 40h [15:2] to ACPI base address.
+ 3. set PMC PCI offset 44h [7] to enable ACPI base address.
+ 4. program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1].
+ 5. Program "ACPI Base Destination ID"
+ For SPT-LP: Program PCR[DMI] + 27B8h[31:0] to 0x23A0
+ For SPT-H: Program PCR[DMI] + 27B8h[31:0] to 0x23A8
+
+ @param[in] Address Address for ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseSet (
+ IN UINT16 Address
+ )
+{
+ UINTN PmcBase;
+ UINT32 Dmic;
+ UINT32 Data32;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (((Address & 0x00FF) != 0) ||
+ (Address == 0)) {
+ DEBUG ((DEBUG_ERROR, "PchAcpiBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchAcpiBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Disable ABASE in PMC Device first before changing base address.
+ //
+ MmioAnd8 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ (UINT8) ~B_PCH_PMC_ACPI_CNT_ACPI_EN
+ );
+ //
+ // Program ABASE in PMC Device
+ //
+ MmioAndThenOr16 (
+ PmcBase + R_PCH_PMC_ACPI_BASE,
+ (UINT16) (~B_PCH_PMC_ACPI_BASE_BAR),
+ Address
+ );
+ //
+ // Enable ABASE in PMC Device
+ //
+ MmioOr8 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ B_PCH_PMC_ACPI_CNT_ACPI_EN
+ );
+ //
+ // Program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1]
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_ACPIBA,
+ (0x00FC0001 + Address)
+ );
+ //
+ // Program "ACPI Base Destination ID"
+ // For SPT-LP:
+ // Program PCR[DMI] + 27B8h[31:0] to 0x23A0
+ // For SPT-H:
+ // Program PCR[DMI] + 27B8h[31:0] to 0x23A8
+ //
+ if (PchSeries == PchLp) {
+ Data32 = 0x23A0;
+ } else {
+ Data32 = 0x23A8;
+ }
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_ACPIBDID,
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH ACPI base address.
+
+ @param[out] Address Address of ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseGet (
+ OUT UINT16 *Address
+ )
+{
+ UINTN PmcBase;
+
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchAcpiBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ *Address = MmioRead16 (PmcBase + R_PCH_PMC_ACPI_BASE) & B_PCH_PMC_ACPI_BASE_BAR;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH PWRM base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [8] to diable PWRM base address first before changing PWRM base address.
+ 2. program PMC PCI offset 48h [31:16] to PM base address.
+ 3. set PMC PCI offset 44h [8] to enable PWRM base address.
+ 4. program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ 5. Program "PM Base Control"
+ For SPT-LP: Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0]
+ For SPT-H: Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A8]
+
+ @param[in] Address Address for PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseSet (
+ IN UINT32 Address
+ )
+{
+ UINTN PmcBase;
+ UINT32 Dmic;
+ UINT32 Data32;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (((Address & (~B_PCH_PMC_PWRM_BASE_BAR)) != 0) ||
+ (Address == 0)) {
+ DEBUG ((DEBUG_ERROR, "PchPwrmBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPwrmBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Disable PWRMBASE in PMC Device first before changing PWRM base address.
+ //
+ MmioAnd16 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ (UINT16) ~B_PCH_PMC_ACPI_CNT_PWRM_EN
+ );
+ //
+ // Program PWRMBASE in PMC Device
+ //
+ MmioAndThenOr32 (
+ PmcBase + R_PCH_PMC_PWRM_BASE,
+ (UINT32) (~B_PCH_PMC_PWRM_BASE_BAR),
+ Address
+ );
+ //
+ // Enable PWRMBASE in PMC Device
+ //
+ MmioOr16 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ B_PCH_PMC_ACPI_CNT_PWRM_EN
+ );
+ //
+ // Program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ // Program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_PMBASEA,
+ ((Address & 0xFFFF0000) | (Address >> 16))
+ );
+ //
+ // Program "PM Base Control"
+ // For SPT-LP:
+ // Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0]
+ // For SPT-H:
+ // Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A8]
+ //
+ if (PchSeries == PchLp) {
+ Data32 = 0x800023A0;
+ } else {
+ Data32 = 0x800023A8;
+ }
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_PMBASEC,
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH PWRM base address.
+
+ @param[out] Address Address of PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseGet (
+ OUT UINT32 *Address
+ )
+{
+ UINTN PmcBase;
+
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchPwrmBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ *Address = MmioRead32 (PmcBase + R_PCH_PMC_PWRM_BASE) & B_PCH_PMC_PWRM_BASE_BAR;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH TCO base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 2. program Smbus PCI offset 50h [15:5] to TCO base address.
+ 3. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 4. program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [Smbus PCI offset 50h[15:5], 1].
+
+ @param[in] Address Address for TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseSet (
+ IN UINT16 Address
+ )
+{
+ UINTN SmbusBase;
+ UINT32 Dmic;
+
+ if ((Address & ~B_PCH_SMBUS_TCOBASE_BAR) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchTcoBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchTcoBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ SmbusBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ if (MmioRead16 (SmbusBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Verify TCO base is not locked.
+ //
+ if ((MmioRead8 (SmbusBase + R_PCH_SMBUS_TCOCTL) & B_PCH_SMBUS_TCOCTL_TCO_BASE_LOCK) != 0) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Disable TCO in SMBUS Device first before changing base address.
+ //
+ MmioAnd16 (
+ SmbusBase + R_PCH_SMBUS_TCOCTL,
+ (UINT16) ~B_PCH_SMBUS_TCOCTL_TCO_BASE_EN
+ );
+ //
+ // Program TCO in SMBUS Device
+ //
+ MmioAndThenOr16 (
+ SmbusBase + R_PCH_SMBUS_TCOBASE,
+ (UINT16) (~B_PCH_SMBUS_TCOBASE_BAR),
+ Address
+ );
+ //
+ // Enable TCO in SMBUS Device
+ //
+ MmioOr16 (
+ SmbusBase + R_PCH_SMBUS_TCOCTL,
+ B_PCH_SMBUS_TCOCTL_TCO_BASE_EN
+ );
+ //
+ // Program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [SMBUS PCI offset 50h[15:5], 1].
+ //
+ PchPcrWrite16 (
+ PID_DMI, R_PCH_PCR_DMI_TCOBASE,
+ (Address | BIT1)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH TCO base address.
+
+ @param[out] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseGet (
+ OUT UINT16 *Address
+ )
+{
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read "TCO Base Address" PCR[DMI] + 2778h[15:5]
+ // Don't read TCO base address from SMBUS PCI register since SMBUS might be disabled.
+ //
+ PchPcrRead16 (
+ PID_DMI, R_PCH_PCR_DMI_TCOBASE,
+ Address
+ );
+ *Address &= B_PCH_PCR_DMI_TCOBASE_TCOBA;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI generic IO range.
+ For generic IO range, the base address must align to 4 and less than 0xFFFF, and the length must be power of 2
+ and less than or equal to 256. Moreover, the address must be length aligned.
+ This function basically checks the address and length, which should not overlap with all other generic ranges.
+ If no more generic range register available, it returns out of resource error.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Some IO ranges below 0x100 have fixed target. The target might be ITSS,RTC,LPC,PMC or terminated inside P2SB
+ but all predefined and can't be changed. IO range below 0x100 will be rejected in this function except below ranges:
+ 0x00-0x1F,
+ 0x44-0x4B,
+ 0x54-0x5F,
+ 0x68-0x6F,
+ 0x80-0x8F,
+ 0xC0-0xFF
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ PCH_LPC_GEN_IO_RANGE_LIST LpcGenIoRangeList;
+ UINTN LpcBase;
+ UINTN Index;
+ UINTN BaseAddr;
+ UINTN MaskLength;
+ UINTN TempMaxAddr;
+ UINT32 Data32;
+ UINTN ArraySize;
+ static struct EXCEPT_RANGE {
+ UINT8 Start;
+ UINT8 Length;
+ } ExceptRanges[] = { {0x00, 0x20}, {0x44, 0x08}, {0x54, 0x0C}, {0x68, 0x08}, {0x80, 0x10}, {0xC0, 0x40} };
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ //
+ // For generic IO range, the base address must align to 4 and less than 0xFFFF,
+ // the length must be power of 2 and less than or equal to 256, and the address must be length aligned.
+ // IO range below 0x100 will be rejected in this function except below ranges:
+ // 0x00-0x1F,
+ // 0x44-0x4B,
+ // 0x54-0x5F,
+ // 0x68-0x6F,
+ // 0x80-0x8F,
+ // 0xC0-0xFF
+ //
+ if (((Length & (Length - 1)) != 0) ||
+ ((Address & (UINT16) ~B_PCH_LPC_GENX_DEC_IOBAR) != 0) ||
+ (Length > 256)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Address < 0x100) {
+ ArraySize = sizeof (ExceptRanges) / sizeof (struct EXCEPT_RANGE);
+ for (Index = 0; Index < ArraySize; Index++) {
+ if ((Address >= ExceptRanges[Index].Start) &&
+ ((Address + Length) <= ((UINTN) ExceptRanges[Index].Start + (UINTN) ExceptRanges[Index].Length))) {
+ break;
+ }
+ }
+ if (Index >= ArraySize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // check if range overlap
+ //
+ Status = PchLpcGenIoRangeGet (&LpcGenIoRangeList);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ MaskLength = LpcGenIoRangeList.Range[Index].Length;
+ if (BaseAddr == 0) {
+ continue;
+ }
+ if (((Address >= BaseAddr) && (Address < (BaseAddr + MaskLength))) ||
+ (((Address + Length) > BaseAddr) && ((Address + Length) <= (BaseAddr + MaskLength)))) {
+ if ((Address >= BaseAddr) && (Length <= MaskLength)) {
+ //
+ // return SUCCESS while range is covered.
+ //
+ return EFI_SUCCESS;
+ }
+
+ if ((Address + Length) > (BaseAddr + MaskLength)) {
+ TempMaxAddr = Address + Length;
+ } else {
+ TempMaxAddr = BaseAddr + MaskLength;
+ }
+ if (Address > BaseAddr) {
+ Address = (UINT16) BaseAddr;
+ }
+ Length = TempMaxAddr - Address;
+ break;
+ }
+ }
+ //
+ // If no range overlap
+ //
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ //
+ // Find a empty register
+ //
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ if (BaseAddr == 0) {
+ break;
+ }
+ }
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Data32);
+ if ((Data32 & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC/eSPI generic IO range register accordingly.
+ //
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ Data32 = (UINT32) (((Length - 1) << 16) & B_PCH_LPC_GENX_DEC_IODRA);
+ Data32 |= (UINT32) Address;
+ Data32 |= B_PCH_LPC_GENX_DEC_EN;
+ //
+ // Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ //
+ MmioWrite32 (
+ LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4,
+ Data32
+ );
+ //
+ // Program LPC Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, (UINT16) (R_PCH_PCR_DMI_LPCLGIR1 + Index * 4),
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH LPC/eSPI generic IO range list.
+ This function returns a list of base address, length, and enable for all LPC/eSPI generic IO range regsiters.
+
+ @param[out] LpcGenIoRangeList Return all LPC/eSPI generic IO range register status.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeGet (
+ OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList
+ )
+{
+ UINTN Index;
+ UINTN LpcBase;
+ UINT32 Data32;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ if (LpcGenIoRangeList == NULL) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ Data32 = MmioRead32 (LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4);
+ LpcGenIoRangeList->Range[Index].BaseAddr = Data32 & B_PCH_LPC_GENX_DEC_IOBAR;
+ LpcGenIoRangeList->Range[Index].Length = ((Data32 & B_PCH_LPC_GENX_DEC_IODRA) >> 16) + 4;
+ LpcGenIoRangeList->Range[Index].Enable = Data32 & B_PCH_LPC_GENX_DEC_EN;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI memory range decoding.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program LPC/eSPI PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC/eSPI PCI Offset 98h [31:16, 0] to [Address, 1].
+ 3. Program LPC/eSPI Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ )
+{
+ UINTN LpcBase;
+ UINT32 Dmic;
+
+ if ((Address & (~B_PCH_LPC_LGMR_MA)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // Program LPC/eSPI PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ //
+ MmioAnd32 (
+ LpcBase + R_PCH_LPC_LGMR,
+ (UINT32) ~B_PCH_LPC_LGMR_LMRD_EN
+ );
+ //
+ // Program LPC/eSPI PCI Offset 98h [31:16, 0] to [Address, 1].
+ //
+ MmioWrite32 (
+ LpcBase + R_PCH_LPC_LGMR,
+ (Address | B_PCH_LPC_LGMR_LMRD_EN)
+ );
+ //
+ // Program LPC Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_LPCGMR,
+ (Address | B_PCH_LPC_LGMR_LMRD_EN)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH LPC/eSPI memory range decoding address.
+
+ @param[out] Address Address of LPC/eSPI memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeGet (
+ OUT UINT32 *Address
+ )
+{
+ UINTN LpcBase;
+
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ *Address = MmioRead32 (LpcBase + R_PCH_LPC_LGMR) & B_PCH_LPC_LGMR_MA;
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH BIOS range deocding.
+ This will check General Control and Status bit 10 (GCS.BBS) to identify SPI or LPC/eSPI and program BDE register accordingly.
+ Please check EDS for detail of BiosDecodeEnable bit definition.
+ bit 15: F8-FF Enable
+ bit 14: F0-F8 Enable
+ bit 13: E8-EF Enable
+ bit 12: E0-E8 Enable
+ bit 11: D8-DF Enable
+ bit 10: D0-D7 Enable
+ bit 9: C8-CF Enable
+ bit 8: C0-C7 Enable
+ bit 7: Legacy F Segment Enable
+ bit 6: Legacy E Segment Enable
+ bit 5: Reserved
+ bit 4: Reserved
+ bit 3: 70-7F Enable
+ bit 2: 60-6F Enable
+ bit 1: 50-5F Enable
+ bit 0: 40-4F Enable
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
+ 2. program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ )
+{
+ UINTN BaseAddr;
+ UINT32 DmiGcsBbs;
+ UINT32 Dmic;
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchBiosDecodeEnableSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_GCS, &DmiGcsBbs);
+ DmiGcsBbs &= B_PCH_PCR_DMI_BBS;
+ //
+ // Check General Control and Status (GCS) [10]
+ // '0': SPI
+ // '1': LPC/eSPI
+ //
+ if (DmiGcsBbs == 0) {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ //
+ // if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_PCH_SPI_BDE, BiosDecodeEnable);
+ } else {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_PCH_LPC_BDE, BiosDecodeEnable);
+ }
+
+ //
+ // program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCBDE, BiosDecodeEnable);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO decode ranges.
+ Program LPC/eSPI I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+ Bit 12: FDD range
+ Bit 9:8: LPT range
+ Bit 6:4: ComB range
+ Bit 2:0: ComA range
+
+ @param[in] LpcIoDecodeRanges LPC/eSPI IO decode ranges bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ )
+{
+ UINTN LpcBaseAddr;
+ UINT32 Dmic;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // check if setting is identical
+ //
+ if (LpcIoDecodeRanges == MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOD)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC/eSPI PCI offset 80h.
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOD, LpcIoDecodeRanges);
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCIOD, LpcIoDecodeRanges);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO enable decoding.
+ Setup LPC/eSPI I/O Enables, PCR[DMI] + 2774h[15:0] to the same value program in LPC/eSPI PCI offset 82h.
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition.
+
+ @param[in] LpcIoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ )
+{
+ UINTN LpcBaseAddr;
+ UINT32 Dmic;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ if (LpcIoEnableDecoding == MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOE)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC/eSPI PCI offset 82h.
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOE, LpcIoEnableDecoding);
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2774h[15:0] to the same value programmed in LPC/eSPI PCI offset 82h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCIOE, LpcIoEnableDecoding);
+ return EFI_SUCCESS;
+}
+
+
+//
+// Root Port Destination ID tables
+//
+// PCH-LP RPR destination ID table
+//
+UINT16 mPchLpRprDidTable[] = {
+ 0x2188, // Dest ID of RP1
+ 0x2189, // Dest ID of RP2
+ 0x218A, // Dest ID of RP3
+ 0x218B, // Dest ID of RP4
+ 0x2198, // Dest ID of RP5
+ 0x2199, // Dest ID of RP6
+ 0x219A, // Dest ID of RP7
+ 0x219B, // Dest ID of RP8
+ 0x21A8, // Dest ID of RP9
+ 0x21A9, // Dest ID of RP10
+ 0x21AA, // Dest ID of RP11
+ 0x21AB // Dest ID of RP12
+};
+
+//
+// PCH-H RPR destination ID table
+//
+UINT16 mPchHRprDidTable[] = {
+ 0x2180, // Dest ID of RP1
+ 0x2181, // Dest ID of RP2
+ 0x2182, // Dest ID of RP3
+ 0x2183, // Dest ID of RP4
+ 0x2188, // Dest ID of RP5
+ 0x2189, // Dest ID of RP6
+ 0x218A, // Dest ID of RP7
+ 0x218B, // Dest ID of RP8
+ 0x2198, // Dest ID of RP9
+ 0x2199, // Dest ID of RP10
+ 0x219A, // Dest ID of RP11
+ 0x219B, // Dest ID of RP12
+ 0x21A8, // Dest ID of RP13
+ 0x21A9, // Dest ID of RP14
+ 0x21AA, // Dest ID of RP15
+ 0x21AB, // Dest ID of RP16
+ 0x21B8, // Dest ID of RP17
+ 0x21B9, // Dest ID of RP18
+ 0x21BA, // Dest ID of RP19
+ 0x21BB, // Dest ID of RP20
+ 0x21C0, // Dest ID of RP21 (KBL-PCH-H only)
+ 0x21C1, // Dest ID of RP22 (KBL-PCH-H only)
+ 0x21C2, // Dest ID of RP23 (KBL-PCH-H only)
+ 0x21C3 // Dest ID of RP24 (KBL-PCH-H only)
+};
+
+/**
+ Set PCH IO port 80h cycle decoding to PCIE root port.
+ System BIOS is likely to do this very soon after reset before PCI bus enumeration.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ 2. Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'. Use byte write on GCS+1 and leave the BILD bit which is RWO.
+
+ @param[in] RpNumber PCIE root port physical number.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+EFIAPI
+PchIoPort80DecodeSet (
+ IN UINTN RpNumber
+ )
+{
+ UINT32 Dmic;
+ UINT16 *PchRprDidTable;
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchIoPort80DecodeSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// IO port 80h is typically used by decoder/LED hardware for debug purposes.
+ /// By default PCH will forward IO port 80h cycles to LPC bus. The Reserved Page Route (RPR) bit
+ /// of General Control and Status register, located at PCR[DMI] + 274Ch[11] , allows software to
+ /// re-direct IO port 80h cycles to PCIe bus so that a target (for example, a debug card) on
+ /// PCIe bus can receive and claim these cycles.
+ /// The "RPR Destination ID", PCR[DMI] + 274Ch[31:16] need to be set accordingly to point
+ /// to the root port that decode this range. Reading from Port 80h may not return valid values
+ /// if the POST-card itself do not shadow the writes. Unlike LPC, PCIe does not shadow the Port 80 writes.
+ ///
+
+ if (GetPchSeries () == PchLp) {
+ if (RpNumber >= sizeof (mPchLpRprDidTable) / sizeof (mPchLpRprDidTable[0]) ) {
+ return EFI_UNSUPPORTED;
+ }
+ PchRprDidTable = mPchLpRprDidTable;
+ } else {
+ if (RpNumber >= sizeof (mPchHRprDidTable) / sizeof (mPchHRprDidTable[0]) ) {
+ return EFI_UNSUPPORTED;
+ }
+ PchRprDidTable = mPchHRprDidTable;
+ }
+
+ //
+ // Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_GCS + 2, PchRprDidTable[RpNumber]);
+ //
+ // Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'.
+ // Use byte write on GCS+1 and leave the BILD bit which is RWO.
+ //
+ PchPcrAndThenOr8 (PID_DMI, R_PCH_PCR_DMI_GCS + 1, 0xFF, (B_PCH_PCR_DMI_RPR >> 8));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get IO APIC regsiters base address.
+ It returns IO APIC INDEX, DATA, and EOI regsiter address once the parameter is not NULL.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] IoApicIndex Buffer of IO APIC INDEX regsiter address
+ @param[out] IoApicData Buffer of IO APIC DATA regsiter address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchIoApicBaseGet (
+ OPTIONAL OUT UINT32 *IoApicIndex,
+ OPTIONAL OUT UINT32 *IoApicData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 RegIoac;
+ UINT32 RangeSelect;
+
+ Status = PchP2sbCfgGet16 (R_PCH_P2SB_IOAC, &RegIoac);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RangeSelect = (RegIoac & B_PCH_P2SB_IOAC_ASEL) << N_PCH_IO_APIC_ASEL;
+
+ if (IoApicIndex != NULL) {
+ *IoApicIndex = R_PCH_IO_APIC_INDEX + RangeSelect;
+ }
+ if (IoApicData != NULL) {
+ *IoApicData = R_PCH_IO_APIC_DATA + RangeSelect;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get HPET base address.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] HpetBase Buffer of HPET base address
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchHpetBaseGet (
+ OUT UINT32 *HpetBase
+ )
+{
+ EFI_STATUS Status;
+ UINT8 RegHptc;
+
+ if (HpetBase == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchHpetBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PchP2sbCfgGet8 (R_PCH_P2SB_HPTC, &RegHptc);
+
+ switch (RegHptc & B_PCH_P2SB_HPTC_AS) {
+ case 0:
+ *HpetBase = V_PCH_HPET_BASE0;
+ break;
+ case 1:
+ *HpetBase = V_PCH_HPET_BASE1;
+ break;
+ case 2:
+ *HpetBase = V_PCH_HPET_BASE2;
+ break;
+ case 3:
+ *HpetBase = V_PCH_HPET_BASE3;
+ break;
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
new file mode 100644
index 0000000000..446703d918
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH cycle decoding Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchCycleDecodingLib
+FILE_GUID = 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchCycleDecodingLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+PchP2sbLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchCycleDecodingLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c
new file mode 100644
index 0000000000..277923bdcc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c
@@ -0,0 +1,146 @@
+/** @file
+ PCH Gbe Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+
+/**
+ Check whether GbE region is valid
+ Check SPI region directly since GbE might be disabled in SW.
+
+ @retval TRUE Gbe Region is valid
+ @retval FALSE Gbe Region is invalid
+**/
+BOOLEAN
+PchIsGbeRegionValid (
+ VOID
+ )
+{
+ UINT32 SpiBar;
+ SpiBar = MmioRead32 (MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI)
+ + R_PCH_SPI_BAR0) & ~B_PCH_SPI_BAR0_MASK;
+ ASSERT (SpiBar != 0);
+ if (MmioRead32 (SpiBar + R_PCH_SPI_FREG3_GBE) != B_PCH_SPI_FREGX_BASE_MASK) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Returns GbE over PCIe port number based on a soft strap.
+
+ @return Root port number (1-based)
+ @retval 0 GbE over PCIe disabled
+**/
+UINT32
+PchGetGbePortNumber (
+ VOID
+ )
+{
+ UINT32 GbePortSel;
+ UINT32 PcieStrapFuse;
+
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_STRPFUSECFG1_REG_BASE, &PcieStrapFuse);
+ if ((PcieStrapFuse & B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIE_PEN) == 0) {
+ return 0; // GbE disabled
+ }
+ GbePortSel = (PcieStrapFuse & B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL) >> N_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL;
+ if (GetPchSeries () == PchLp) {
+ switch (GbePortSel) {
+ case 0: return 3;
+ case 1: return 4;
+ case 2: return 5;
+ case 3: return 9;
+ case 4: return 10;
+ }
+ } else {
+ switch (GbePortSel) {
+ case 0: return 4;
+ case 1: return 5;
+ case 2: return 9;
+ case 3: return 12;
+ case 4: return 13;
+ }
+ }
+ DEBUG ((DEBUG_ERROR, "Invalid GbE port\n"));
+ ASSERT (FALSE);
+ return 0;
+}
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbePresent (
+ VOID
+ )
+{
+ UINT32 PwrmBase;
+ UINT32 FuseDis2State;
+ //
+ // Check PMC strap/fuse
+ //
+ PchPwrmBaseGet (&PwrmBase);
+ FuseDis2State = MmioRead32 (PwrmBase + R_PCH_PWRM_FUSE_DIS_RD_2);
+ if (FuseDis2State & B_PCH_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS) {
+ return FALSE;
+ }
+ //
+ // Check FIA strap/fuse
+ //
+ if (PchGetGbePortNumber () == 0) {
+ return FALSE;
+ }
+ //
+ // Check GbE NVM
+ //
+ if (PchIsGbeRegionValid () == FALSE) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @deprecated Use PchIsGbePresent instead.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbeAvailable (
+ VOID
+ )
+{
+ return PchIsGbePresent ();
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf
new file mode 100644
index 0000000000..b05d82fce1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH Gbe Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchGbeLib
+FILE_GUID = FC022ED0-6EB3-43E1-A740-0BA27CBBD010
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchGbeLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+PchCycleDecodingLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchGbeLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c
new file mode 100644
index 0000000000..d3e6094954
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c
@@ -0,0 +1,928 @@
+/** @file
+ PCH HSIO Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchHsioLib.h>
+
+/**
+ The function returns the Port Id and lane owner for the specified lane
+
+ @param[in] PhyMode Phymode that needs to be checked
+ @param[out] PortId Common Lane End Point ID
+ @param[out] LaneOwner Lane Owner
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid lane number
+**/
+EFI_STATUS
+EFIAPI
+PchGetLaneInfo (
+ IN UINT32 LaneNum,
+ OUT UINT8 *PortId,
+ OUT UINT8 *LaneOwner
+ )
+{
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGeneration;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ Los1 = 0;
+ Los2 = 0;
+ Los3 = 0;
+ Los4 = 0;
+
+ PchSeries = GetPchSeries ();
+ PchGeneration = GetPchGeneration ();
+
+ if (((LaneNum > 15) && (PchSeries == PchLp)) ||
+ ((LaneNum > 29) && (PchSeries == PchH) && (PchGeneration == SklPch)) ||
+ (LaneNum > 33) ) {
+ return EFI_INVALID_PARAMETER;
+ } else if (LaneNum < 8) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ } else if (LaneNum < 16) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+ } else if (LaneNum < 24) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ }
+
+ if (PchSeries == PchLp) {
+ switch (LaneNum) {
+ case 0:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L0O));
+ *PortId = PID_MODPHY0;
+ break;
+ case 1:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L1O) >>4);
+ *PortId = PID_MODPHY0;
+ break;
+ case 2:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L2O) >>8);
+ *PortId = PID_MODPHY0;
+ break;
+ case 3:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L3O) >>12);
+ *PortId = PID_MODPHY0;
+ break;
+ case 4:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L4O) >>16);
+ *PortId = PID_MODPHY0;
+ break;
+ case 5:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L5O) >>20);
+ *PortId = PID_MODPHY0;
+ break;
+ case 6:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L6O) >>24);
+ *PortId = PID_MODPHY1;
+ break;
+ case 7:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L7O) >>28);
+ *PortId = PID_MODPHY1;
+ break;
+ case 8:
+ *LaneOwner = (UINT8) (Los2 & B_PCH_PCR_FIA_L8O);
+ *PortId = PID_MODPHY1;
+ break;
+ case 9:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L9O) >>4);
+ *PortId = PID_MODPHY1;
+ break;
+ case 10:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L10O) >>8);
+ *PortId = PID_MODPHY2;
+ break;
+ case 11:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L11O) >>12);
+ *PortId = PID_MODPHY2;
+ break;
+ case 12:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L12O) >>16);
+ *PortId = PID_MODPHY2;
+ break;
+ case 13:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L13O) >>20);
+ *PortId = PID_MODPHY2;
+ break;
+ case 14:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L14O) >>24);
+ *PortId = PID_MODPHY2;
+ break;
+ case 15:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L15O) >>28);
+ *PortId = PID_MODPHY2;
+ break;
+ }
+ } else {
+ switch (LaneNum) {
+ case 0:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L0O));
+ *PortId = PID_MODPHY0;
+ break;
+ case 1:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L1O) >>4);
+ *PortId = PID_MODPHY0;
+ break;
+ case 2:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L2O) >>8);
+ *PortId = PID_MODPHY0;
+ break;
+ case 3:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L3O) >>12);
+ *PortId = PID_MODPHY0;
+ break;
+ case 4:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L4O) >>16);
+ *PortId = PID_MODPHY0;
+ break;
+ case 5:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L5O) >>20);
+ *PortId = PID_MODPHY0;
+ break;
+ case 6:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L6O) >>24);
+ *PortId = PID_MODPHY1;
+ break;
+ case 7:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L7O) >>28);
+ *PortId = PID_MODPHY1;
+ break;
+ case 8:
+ *LaneOwner = (UINT8) (Los2 & B_PCH_PCR_FIA_L8O);
+ *PortId = PID_MODPHY1;
+ break;
+ case 9:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L9O) >>4);
+ *PortId = PID_MODPHY1;
+ break;
+ case 10:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L10O) >>8);
+ *PortId = PID_MODPHY1;
+ break;
+ case 11:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L11O) >>12);
+ *PortId = PID_MODPHY1;
+ break;
+ case 12:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L12O) >>16);
+ *PortId = PID_MODPHY1;
+ break;
+ case 13:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L13O) >>20);
+ *PortId = PID_MODPHY1;
+ break;
+ case 14:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L14O) >>24);
+ *PortId = PID_MODPHY2;
+ break;
+ case 15:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L15O) >>28);
+ *PortId = PID_MODPHY2;
+ break;
+ case 16:
+ *LaneOwner = (UINT8) (Los3 & B_PCH_PCR_FIA_L16O);
+ *PortId = PID_MODPHY2;
+ break;
+ case 17:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L17O) >>4);
+ *PortId = PID_MODPHY2;
+ break;
+ case 18:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L18O) >>8);
+ *PortId = PID_MODPHY2;
+ break;
+ case 19:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L19O) >>12);
+ *PortId = PID_MODPHY2;
+ break;
+ case 20:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L20O) >>16);
+ *PortId = PID_MODPHY2;
+ break;
+ case 21:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L21O) >>20);
+ *PortId = PID_MODPHY2;
+ break;
+ case 22:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L22O) >>24);
+ *PortId = PID_MODPHY3;
+ break;
+ case 23:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L23O) >>28);
+ *PortId = PID_MODPHY3;
+ break;
+ case 24:
+ *LaneOwner = (UINT8) (Los4 & B_PCH_PCR_FIA_L24O);
+ *PortId = PID_MODPHY3;
+ break;
+ case 25:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L25O) >>4);
+ *PortId = PID_MODPHY3;
+ break;
+ case 26:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L26O) >>8);
+ *PortId = PID_MODPHY3;
+ break;
+ case 27:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L27O) >>12);
+ *PortId = PID_MODPHY3;
+ break;
+ case 28:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L28O) >>16);
+ *PortId = PID_MODPHY3;
+ break;
+ case 29:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L29O) >>20);
+ *PortId = PID_MODPHY3;
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ //
+ // Lanes 30-33 don't have ownership registers and are always configured to PCIE
+ //
+ *LaneOwner = V_PCH_PCR_FIA_LANE_OWN_PCIEDMI;
+ *PortId = PID_MODPHY4;
+ break;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[out] LaneNum GBE Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetGbeLaneNum (
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ } else if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ } else if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L12O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 12;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L13O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 13;
+ return EFI_SUCCESS;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L18O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 18;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L21O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 21;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L22O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 22;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] Usb3LaneIndex USB3 Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetUsb3LaneNum (
+ UINT32 Usb3LaneIndex,
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ switch (Usb3LaneIndex) {
+ case 0:
+ if ((Los1 & B_PCH_PCR_FIA_L0O) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 0;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L1O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 1;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los1 & B_PCH_PCR_FIA_L2O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 2;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los1 & B_PCH_PCR_FIA_L3O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 3;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los1 & B_PCH_PCR_FIA_L4O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 4;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los1 & B_PCH_PCR_FIA_L5O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 5;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported USB3 Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ switch (Usb3LaneIndex) {
+ case 0:
+ if ((Los1 & B_PCH_PCR_FIA_L0O) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 0;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L1O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 1;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los1 & B_PCH_PCR_FIA_L2O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 2;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los1 & B_PCH_PCR_FIA_L3O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 3;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los1 & B_PCH_PCR_FIA_L4O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 4;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los1 & B_PCH_PCR_FIA_L5O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 5;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 8:
+ if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 9:
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported USB3 Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] SataLaneIndex Sata Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetSataLaneNum (
+ UINT32 SataLaneIndex,
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ switch (SataLaneIndex) {
+ case 0:
+ if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los2 & B_PCH_PCR_FIA_L11O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 11;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L14O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 14;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los2 & B_PCH_PCR_FIA_L15O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 15;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported SATA Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ switch (SataLaneIndex) {
+ case 0:
+ if (((Los3 & B_PCH_PCR_FIA_L18O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 18;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L22O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 22;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los3 & B_PCH_PCR_FIA_L19O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 19;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L23O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 23;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if ((Los4 & B_PCH_PCR_FIA_L24O) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 24;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los4 & B_PCH_PCR_FIA_L25O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 25;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los4 & B_PCH_PCR_FIA_L26O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 26;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los4 & B_PCH_PCR_FIA_L27O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 27;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los4 & B_PCH_PCR_FIA_L28O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 28;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los4 & B_PCH_PCR_FIA_L29O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 29;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported SATA Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] PcieLaneIndex PCIE Root Port Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetPcieLaneNum (
+ UINT32 PcieLaneIndex,
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ switch (PcieLaneIndex) {
+ case 0:
+ if (((Los1 & B_PCH_PCR_FIA_L4O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 4;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L5O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 5;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los2 & B_PCH_PCR_FIA_L11O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 11;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 8:
+ if (((Los2 & B_PCH_PCR_FIA_L12O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 12;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 9:
+ if (((Los2 & B_PCH_PCR_FIA_L13O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 13;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 10:
+ if (((Los2 & B_PCH_PCR_FIA_L14O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 14;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 11:
+ if (((Los2 & B_PCH_PCR_FIA_L15O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 15;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCIE Root Port Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ switch (PcieLaneIndex) {
+ case 0:
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los2 & B_PCH_PCR_FIA_L11O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 11;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los2 & B_PCH_PCR_FIA_L12O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 12;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los2 & B_PCH_PCR_FIA_L13O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 13;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 8:
+ if (((Los3 & B_PCH_PCR_FIA_L18O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 18;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 9:
+ if (((Los3 & B_PCH_PCR_FIA_L19O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 19;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 10:
+ if (((Los3 & B_PCH_PCR_FIA_L20O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 20;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 11:
+ if (((Los3 & B_PCH_PCR_FIA_L21O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 21;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 12:
+ if (((Los3 & B_PCH_PCR_FIA_L22O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 22;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 13:
+ if (((Los3 & B_PCH_PCR_FIA_L23O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 23;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 14:
+ if ((Los4 & B_PCH_PCR_FIA_L24O) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 24;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 15:
+ if (((Los4 & B_PCH_PCR_FIA_L25O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 25;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 16:
+ if (((Los4 & B_PCH_PCR_FIA_L26O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 26;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 17:
+ if (((Los4 & B_PCH_PCR_FIA_L27O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 27;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 18:
+ if (((Los4 & B_PCH_PCR_FIA_L28O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 28;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 19:
+ if (((Los4 & B_PCH_PCR_FIA_L29O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 29;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 20:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 30;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ case 21:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 31;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ case 22:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 32;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ case 23:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 33;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCIE Root Port Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get HSIO lane representation needed to perform any operation on the lane.
+
+ @param[in] LaneIndex Number of the HSIO lane
+ @param[out] HsioLane HSIO lane representation
+**/
+VOID
+HsioGetLane (
+ IN UINT8 LaneIndex,
+ OUT HSIO_LANE *HsioLane
+ )
+{
+ // SPT-LP
+ // iolane 0 - 5 : 0xEA - 000, 200, 400, 600, 800, a00
+ // iolane 6 - 9 : 0xE9 - 000, 200, 400, 600
+ // iolane 10 - 15 : 0xA9 - 000, 200, 400, 600, 800, a00
+ // SPT-H
+ // iolane 0 - 5 : 0xEA - 000, 200, 400, 600, 800, a00
+ // iolane 6 - 13 : 0xE9 - 000, 200, 400, 600, 800, a00, c00, e00
+ // iolane 14 - 21 : 0xA9 - 000, 200, 400, 600, 800, a00, c00, e00
+ // iolane 22 - 29 : 0xA8 - 000, 200, 400, 600, 800, a00, c00, e00
+ // KBL-H: as for SKL-H plus the following lanes
+ // iolane 30 - 33 : 0xB0 - 000, 200, 400, 600
+
+ static UINT8 IoLanesLp[] = { 0, 6, 10, 16 };
+ static UINT8 IoLanesH[] = { 0, 6, 14, 22, 30, 34 };
+ static UINT8 Pids[] = { PID_MODPHY0, PID_MODPHY1, PID_MODPHY2, PID_MODPHY3, PID_MODPHY4 };
+
+ UINT8* IoLanes;
+ UINT8 PidMax;
+ UINT32 Index;
+
+ ASSERT (HsioLane != NULL);
+
+ if (GetPchSeries () == PchLp) {
+ IoLanes = IoLanesLp;
+ PidMax = 3;
+ } else {
+ IoLanes = IoLanesH;
+ if (GetPchGeneration () == KblPch) {
+ PidMax = 5;
+ } else {
+ PidMax = 4;
+ }
+ }
+ ASSERT (LaneIndex < IoLanes[PidMax]);
+
+ for (Index = 0; Index < PidMax; ++Index) {
+ if (LaneIndex < IoLanes[Index + 1]) {
+ HsioLane->Index = LaneIndex;
+ HsioLane->Pid = Pids[Index];
+ HsioLane->Base = (LaneIndex - IoLanes[Index]) * 0x200;
+ return;
+ }
+ }
+ ASSERT (FALSE);
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf
new file mode 100644
index 0000000000..f233f3e673
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH HSIO Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchHsioLib
+FILE_GUID = 6B2D3D0D-9A04-4E7C-AE84-1C2EF2E00E2E
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchHsioLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchHsioLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
new file mode 100644
index 0000000000..3f72e006c8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
@@ -0,0 +1,514 @@
+/** @file
+ Pch information library.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+#define PCH_DO_STRINGIFY(x) #x
+#define PCH_STRINGIFY(x) PCH_DO_STRINGIFY(x)
+
+//
+// This module variables are used for cache the static result.
+// @note: please pay attention to the PEI phase, the module variables on ROM
+// and can't be modified.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_STEPPING mPchStepping = PchSteppingMax;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mIsPchSupported = 0xFF;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SERIES mPchSeries = PchUnknownSeries;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_GENERATION mPchGeneration = PchUnknownGeneration;
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+EFIAPI
+PchStepping (
+ VOID
+ )
+{
+ UINT8 RevId;
+ UINT16 LpcDeviceId;
+ UINTN LpcBaseAddress;
+#ifndef MDEPKG_NDEBUG
+ static CHAR8 *UnsupportedPchMsg = "Unsupported PCH. Supported stepping starting from";
+#endif
+
+ if (mPchStepping != PchSteppingMax) {
+ return mPchStepping;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ RevId = MmioRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET);
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_SKL_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchHB0;
+ return PchHB0;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchHC0;
+ return PchHC0;
+
+ case V_PCH_LPC_RID_30:
+ mPchStepping = PchHD0;
+ return PchHD0;
+
+ case V_PCH_LPC_RID_31:
+ mPchStepping = PchHD1;
+ return PchHD1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a %a\n", UnsupportedPchMsg, PCH_STRINGIFY (SKL_PCH_H_MIN_SUPPORTED_STEPPING)));
+ return PchSteppingMax;
+ }
+ }
+
+ if (IS_KBL_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_0:
+ mPchStepping = KblPchHA0;
+ return KblPchHA0;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a %a\n", UnsupportedPchMsg, PCH_STRINGIFY (KBL_PCH_H_MIN_SUPPORTED_STEPPING)));
+ return PchSteppingMax;
+ }
+ }
+
+ if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchLpB0;
+ return PchLpB0;
+
+ case V_PCH_LPC_RID_11:
+ mPchStepping = PchLpB1;
+ return PchLpB1;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchLpC0;
+ return PchLpC0;
+
+ case V_PCH_LPC_RID_21:
+ mPchStepping = PchLpC1;
+ return PchLpC1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a %a\n", UnsupportedPchMsg, PCH_STRINGIFY (PCH_LP_MIN_SUPPORTED_STEPPING)));
+ return PchSteppingMax;
+ }
+ }
+ return PchSteppingMax;
+}
+
+/**
+ Determine if PCH is supported
+
+ @retval TRUE PCH is supported
+ @retval FALSE PCH is not supported
+**/
+BOOLEAN
+IsPchSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT16 LpcVendorId;
+ UINTN LpcBaseAddress;
+
+ if (mIsPchSupported != 0xFF) {
+ return (BOOLEAN) mIsPchSupported;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+ LpcVendorId = MmioRead16 (LpcBaseAddress + PCI_VENDOR_ID_OFFSET);
+
+ ///
+ /// Verify that this is a supported chipset
+ ///
+ if ((LpcVendorId == V_PCH_LPC_VENDOR_ID) &&
+ (IS_PCH_LPC_DEVICE_ID (LpcDeviceId))) {
+ mIsPchSupported = TRUE;
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_ERROR, "PCH code doesn't support the LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ mIsPchSupported = FALSE;
+ return FALSE;
+ }
+}
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+EFIAPI
+GetPchSeries (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT32 PchSeries;
+
+ if (mPchSeries != PchUnknownSeries) {
+ return mPchSeries;
+ }
+
+ LpcDeviceId = GetLpcDid ();
+
+ if (IS_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchH;
+ } else if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchLp;
+ } else {
+ PchSeries = PchUnknownSeries;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchSeries = PchSeries;
+
+ return PchSeries;
+}
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+EFIAPI
+GetPchGeneration (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ PCH_GENERATION PchGen;
+
+ if (mPchGeneration != PchUnknownGeneration) {
+ return mPchGeneration;
+ }
+
+ LpcDeviceId = GetLpcDid ();
+
+ if (IS_SKL_PCH_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchGen = SklPch;
+ } else if (IS_KBL_PCH_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchGen = KblPch;
+ } else {
+ PchGen = PchUnknownGeneration;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchGeneration = PchGen;
+
+ return PchGen;
+}
+
+/**
+ Get PCH SKU type
+
+ @retval PCH_SKU_TYPE Type of PCH SKU
+**/
+PCH_SKU_TYPE
+GetPchSkuType (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+
+ LpcDeviceId = GetLpcDid ();
+
+ if (IS_PCH_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) {
+ return PchMobileSku;
+ } else if (IS_PCH_LPC_DEVICE_ID_DESKTOP (LpcDeviceId)) {
+ return PchDesktopSku;
+ } else if (IS_PCH_LPC_DEVICE_ID_SERVER (LpcDeviceId)) {
+ return PchServerSku;
+ } else {
+ return PchUnknownSku;
+ }
+}
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval Pch Maximum Pcie Root Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPciePortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_PCIE_MAX_ROOT_PORTS;
+
+ case PchH:
+ switch (GetPchGeneration ()) {
+ case SklPch:
+ return SKL_PCH_H_PCIE_MAX_ROOT_PORTS;
+ case KblPch:
+ return KBL_PCH_H_PCIE_MAX_ROOT_PORTS;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Sata Port Number
+
+ @retval Pch Maximum Sata Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxSataPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_AHCI_MAX_PORTS;
+
+ case PchH:
+ return PCH_H_AHCI_MAX_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Usb Maximum Physical Port Number
+
+ @retval Pch Usb Maximum Physical Port Number
+**/
+UINT8
+EFIAPI
+GetPchUsbMaxPhysicalPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb2PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb3PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB3_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB3_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Lpc Did
+
+ @retval UINT16 Lpc Did
+**/
+UINT16
+EFIAPI
+GetLpcDid (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINTN LpcBaseAddress;
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ return LpcDeviceId;
+}
+
+/**
+ Get RST mode supported by the silicon
+
+ @retval RST_MODE RST mode supported by silicon
+**/
+RST_MODE
+EFIAPI
+GetSupportedRstMode (
+ VOID
+ )
+{
+ if (IsPchRaidSupported ()) {
+ return RstPremium;
+ } else if (IsOptaneModeSupported ()) {
+ return RstOptane;
+ } else {
+ return RstUnsupported;
+ }
+}
+
+/**
+ Check if current SKU supports Optane mode
+
+ @retval TRUE This SKU supports Optane mode
+ @retval FALSE This SKU doesn't support Optane mode
+**/
+BOOLEAN
+EFIAPI
+IsOptaneModeSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ BOOLEAN OptaneSupported;
+
+ LpcDeviceId = GetLpcDid ();
+
+ switch (LpcDeviceId) {
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250:
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250:
+ OptaneSupported = TRUE;
+ break;
+ default:
+ OptaneSupported = FALSE;
+ break;
+ }
+
+ return OptaneSupported;
+}
+
+/**
+ Check if current SKU supports RAID feature
+
+ @retval TRUE This SKU supports RAID
+ @retval FALSE This SKU doesn't support RAID
+**/
+BOOLEAN
+EFIAPI
+IsPchRaidSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ BOOLEAN RaidSupported;
+
+ LpcDeviceId = GetLpcDid ();
+
+
+ switch (LpcDeviceId) {
+ case V_PCH_LP_LPC_DEVICE_ID_MB_1: // SPT-LP Base-U (SPT-LP Mobile)
+ case V_PCH_LP_LPC_DEVICE_ID_MB_5: // KBL-LP Base-U (KBL-LP Mobile)
+ case V_PCH_LP_LPC_DEVICE_ID_MB_10: // KBL-LP Mobile (U) iHDCP 2.2 Base
+ case V_SKL_PCH_H_LPC_DEVICE_ID_DT_1: // H110 (SPT-H Desktop)
+ case V_SKL_PCH_H_LPC_DEVICE_ID_DT_6: // B150 (SPT-H Desktop)
+ case V_SKL_PCH_H_LPC_DEVICE_ID_DT_5: // Q150 (SPT-H Desktop)
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250: // B250 (KBL-H Desktop)
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250: // Q250 (KBL-H Desktop)
+ case V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1: // C232 (SPT-H Server)
+ RaidSupported = FALSE;
+ break;
+ default:
+ RaidSupported = TRUE;
+ break;
+ }
+
+ return RaidSupported;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
new file mode 100644
index 0000000000..6fb06eac2f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
@@ -0,0 +1,334 @@
+/** @file
+ Pch information string library.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+/**
+ Structure for PCH stepping string mapping
+**/
+struct PCH_STEPPING_STRING {
+ PCH_STEPPING Stepping;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_STEPPING_STRING mSteppingStrs[] = {
+ {PchHB0, "B0"},
+ {PchHC0, "C0"},
+ {PchHD0, "D0"},
+ {PchHD1, "D1"},
+ {PchLpB0, "B0"},
+ {PchLpB1, "B1"},
+ {PchLpC0, "C0"},
+ {PchLpC1, "C1"},
+ {KblPchHA0, "A0"},
+ {PchSteppingMax, NULL}
+};
+
+/**
+ Structure for PCH series string mapping
+**/
+typedef struct {
+ PCH_SERIES Series;
+ CHAR8 *String;
+} PCH_SERIES_STRING ;
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+PCH_SERIES_STRING mSklPchSeriesStrs[] = {
+ {PchH, "SKL PCH-H"},
+ {PchLp, "SKL PCH-LP"},
+ {PchUnknownSeries, NULL}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+PCH_SERIES_STRING mKblPchSeriesStrs[] = {
+ {PchH, "KBL PCH-H"},
+ {PchUnknownSeries, NULL}
+};
+
+/**
+ Structure for PCH sku string mapping
+**/
+struct PCH_SKU_STRING {
+ UINT16 Id;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_SKU_STRING mSkuStrs[] = {
+ //
+ // SKL PCH H Desktop LPC Device IDs
+ //
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU, "Super SKU"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU, "ES Super SKU"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_0, "Super SKU (locked)"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_1, "H110"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_2, "H170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_3, "Z170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_4, "Q170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_5, "Q150"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_6, "B150"},
+ //
+ // SKL PCH H Server/WS LPC Device IDs
+ //
+ {V_SKL_PCH_H_LPC_DEVICE_ID_SVR_0, "C236"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1, "C232"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_SVR_2, "CM236"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_A14B, "Super SKU (Unlocked)"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU, "ES Super SKU (Unlocked)"},
+ //
+ // SKL PCH H Mobile LPC Device IDs
+ //
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_0, "QM170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_1, "HM170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_3, "QMS180"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_4, "HM175"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_5, "QM175"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_6, "CM238"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_8, "QMS185"},
+ //
+ // SKL PCH LP Mobile LPC Device IDs
+ //
+ {V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_0, "Super SKU (locked)"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_1, "(U) Base SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_2, "(Y) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_3, "(U) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU_1, "Super SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_4, "Super SKU (locked)"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_5, "(U) Base SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_6, "(Y) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_7, "(U) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_8, "(Y) iHDCP 2.2 Premium"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_9, "(U) iHDCP 2.2 Premium"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_10, "(U) iHDCP 2.2 Base"},
+ //
+ // KBL PCH H Desktop LPC Device IDs
+ //
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU, "Super SKU"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_H270, "H270"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z270, "Z270"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q270, "Q270"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250, "Q250"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250, "B250"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_H215, "H215"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z370, "Z370"},
+
+ //
+ // KBL PCH H Server/WS LPC Device IDs
+ //
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_SUPER_SKU, "Super SKU (Unlocked)"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_0, "X290"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_1, "C6xx"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_2, "ES Super SKU Server (Interposer)"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_3, "Super SKU Server"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_4, "C422B"},
+ {0xFFFF, NULL}
+};
+
+/**
+ Get PCH stepping ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchStep Pch stepping
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ IN PCH_STEPPING PchStep,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSteppingStrs[Index].Stepping != PchSteppingMax; Index++) {
+ if (PchStep == mSteppingStrs[Index].Stepping) {
+ StrLength = (UINT32) AsciiStrLen (mSteppingStrs[Index].String);
+ Str = mSteppingStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Stepping
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ AsciiStrCpyS (Buffer, *BufferSize, Str);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH series ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchSeries Pch series
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSeriesStr (
+ IN PCH_SERIES PchSeries,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ PCH_GENERATION PchGen;
+ PCH_SERIES_STRING *SeriesStrs;
+ UINT16 LpcDeviceId;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PchGen = GetPchGeneration ();
+
+ if (PchGen == SklPch) {
+ //
+ // Check if Client/Server ES Super SKU
+ //
+
+ LpcDeviceId = GetLpcDid ();
+
+ if ((LpcDeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU) ||
+ (LpcDeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU)) {
+ SeriesStrs = mKblPchSeriesStrs;
+ } else {
+ SeriesStrs = mSklPchSeriesStrs;
+ }
+ } else if (PchGen == KblPch){
+ SeriesStrs = mKblPchSeriesStrs;
+ } else {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; SeriesStrs[Index].Series != PchUnknownSeries; Index++) {
+ if (PchSeries == SeriesStrs[Index].Series) {
+ StrLength = (UINT32) AsciiStrLen (SeriesStrs[Index].String);
+ Str = SeriesStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Series
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ AsciiStrCpyS (Buffer, *BufferSize, Str);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH Sku ASCII string
+ The return string is zero terminated.
+
+ @param [in] LpcDid LPC device id
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSkuStr (
+ IN UINT16 LpcDid,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSkuStrs[Index].Id != 0xFFFF; Index++) {
+ if (LpcDid == mSkuStrs[Index].Id) {
+ StrLength = (UINT32) AsciiStrLen (mSkuStrs[Index].String);
+ Str = mSkuStrs[Index].String;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Sku
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ AsciiStrCpyS (Buffer, *BufferSize, Str);
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
new file mode 100644
index 0000000000..35566d8243
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PCH information library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchInfoLib
+FILE_GUID = D43F3086-1D7E-4FF5-AE6A-3B0E15B11329
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchInfoLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchInfoLib.c
+PchInfoStrLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c
new file mode 100644
index 0000000000..dba89d3edc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c
@@ -0,0 +1,338 @@
+/** @file
+ PCH P2sb access lib.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+
+/**
+ Get P2SB pci configuration register. (This is internal function)
+ It returns register at Offset of P2SB controller and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchP2sbCfgGet (
+ IN UINTN Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN DevicePresent;
+
+ if ((Offset > 255) ||
+ ((Offset & (Size - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "PchP2sbCfgGet error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ ASSERT (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+
+ switch (Size) {
+ case 4:
+ *(UINT32*) OutData = MmioRead32 (P2sbBase + Offset);
+ break;
+ case 2:
+ *(UINT16*) OutData = MmioRead16 (P2sbBase + Offset);
+ break;
+ case 1:
+ *(UINT8*) OutData = MmioRead8 (P2sbBase + Offset);
+ break;
+ default:
+ break;
+ }
+
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet32 (
+ IN UINTN Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 4, (UINT32*) OutData);
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet16 (
+ IN UINTN Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 2, (UINT32*) OutData);
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 1byte.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet8 (
+ IN UINTN Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 1, (UINT32*) OutData);
+}
+
+/**
+ Set P2SB pci configuration register. (This is internal function)
+ It programs register at Offset of P2SB controller and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchP2sbCfgSet (
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN DevicePresent;
+ UINT32 Data32;
+
+ if ((Offset > 255) ||
+ ((Offset & (Size - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "PchP2sbCfgSet error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data32 = 0;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ ASSERT (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+
+ switch (Size) {
+ case 4:
+ Data32 = MmioRead32 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite32 (P2sbBase + Offset, (UINT32) Data32);
+ break;
+ case 2:
+ Data32 = MmioRead16 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite16 (P2sbBase + Offset, (UINT16) Data32);
+ break;
+ case 1:
+ Data32 = MmioRead8 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite8 (P2sbBase + Offset, (UINT8) Data32);
+ break;
+ default:
+ break;
+ }
+
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet32 (
+ IN UINTN Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 4, AndData, OrData);
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet16 (
+ IN UINTN Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 2, AndData, OrData);
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 1bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet8 (
+ IN UINTN Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 1, AndData, OrData);
+}
+
+/**
+ Hide P2SB device.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchHideP2sb (
+ IN UINTN P2sbBase
+ )
+{
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ return EFI_SUCCESS;
+}
+
+/**
+ Reveal P2SB device.
+ Also return the original P2SB status which is for Hidding P2SB or not after.
+ If OrgStatus is not NULL, then TRUE means P2SB is unhidden,
+ and FALSE means P2SB is hidden originally.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+ @param[out] OrgStatus Original P2SB hidding/unhidden status
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchRevealP2sb (
+ IN UINTN P2sbBase,
+ OUT BOOLEAN *OrgStatus
+ )
+{
+ BOOLEAN DevicePresent;
+
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (OrgStatus != NULL) {
+ *OrgStatus = DevicePresent;
+ }
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf
new file mode 100644
index 0000000000..115175f8a2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PCH P2sb access Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchP2sbLib
+FILE_GUID = FB044F6F-5F9F-48AB-AE12-1C0B829C8AD7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchP2sbLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchP2sbLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
new file mode 100644
index 0000000000..6b8a51d8d2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
@@ -0,0 +1,268 @@
+/** @file
+ PCH PCIE root port library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPcieRpLib.h>
+
+//
+// For SKL PCH-LP, it supports three express port controllers:
+// Controller 1:
+// Port 1-4, Device 28, function 0-3
+// Controller 2:
+// Port 5-8, Device 28, function 4-7
+// Controller 3:
+// port 9-12, Device 29, function 0-3
+// For SKL PCH-H, it supports five express port controllers:
+// Controller 1:
+// Port 1-4, Device 28, function 0-3
+// Controller 2:
+// Port 5-8, Device 28, function 4-7
+// Controller 3:
+// port 9-12, Device 29, function 0-3
+// Controller 4:
+// Port 13-16, Device 29, function 4-7
+// Controller 5:
+// port 17-20, Device 27, function 0-3
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[] = {
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPA, 0 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPB, 4 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPC, 8 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPD, 12 }, // SKL-H and KBL-H only
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPE, 16 }, // SKL-H and KBL-H only
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPF, 20 } // KBL-H only
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mPchPcieControllerInfoSize = sizeof (mPchPcieControllerInfo) / sizeof (mPchPcieControllerInfo[0]);
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchLpRstPcieStorageSupportedPort[] = {
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4
+ RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP5..RP8
+ RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 // RP9..RP12
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSklPchHRstPcieStorageSupportedPort[] = {
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8
+ RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12
+ RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP13..RP16
+ RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 // RP17..RP20
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mKblPchHRstPcieStorageSupportedPort[] = {
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8
+ RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP13..RP16
+ RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, // RP17..RP20
+ RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2 // RP21..RP24
+};
+
+/**
+ Get Pch Pcie Root Port Device and Function Number by Root Port physical Number
+
+ @param[in] RpNumber Root port physical number. (0-based)
+ @param[out] RpDev Return corresponding root port device number.
+ @param[out] RpFun Return corresponding root port function number.
+
+ @retval EFI_SUCCESS Root port device and function is retrieved
+ @retval EFI_INVALID_PARAMETER RpNumber is invalid
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ )
+{
+ UINTN Index;
+ UINTN FuncIndex;
+ UINT32 PciePcd;
+
+ //
+ // if SKL PCH-LP, RpNumber must be < 12.
+ // if SKL PCH-H , RpNumber must be < 20.
+ // if KBL PCH-H , RpNumber must be < 24.
+ //
+ if (RpNumber >= GetPchMaxPciePortNum ()) {
+ DEBUG ((DEBUG_ERROR, "GetPchPcieRpDevFun invalid RpNumber %x", RpNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Index = RpNumber / PCH_PCIE_CONTROLLER_PORTS;
+ FuncIndex = RpNumber - mPchPcieControllerInfo[Index].RpNumBase;
+ *RpDev = mPchPcieControllerInfo[Index].DevNum;
+ PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_PCH_PCR_SPX_PCD, &PciePcd);
+ *RpFun = (PciePcd >> (FuncIndex * S_PCH_PCR_SPX_PCD_RP_FIELD)) & B_PCH_PCR_SPX_PCD_RP1FN;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Root Port physical Number by Pch Pcie Root Port Device and Function Number
+
+ @param[in] RpDev Root port device number.
+ @param[in] RpFun Root port function number.
+ @param[out] RpNumber Return corresponding physical Root Port index (0-based)
+
+ @retval EFI_SUCCESS Physical root port is retrieved
+ @retval EFI_INVALID_PARAMETER RpDev and/or RpFun are invalid
+ @retval EFI_UNSUPPORTED Root port device and function is not assigned to any physical root port
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ )
+{
+ UINTN Index;
+ UINTN FuncIndex;
+ UINT32 PciePcd;
+ UINT8 MaxPorts;
+
+ MaxPorts = GetPchMaxPciePortNum ();
+ if ( !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1) && (RpFun < 8) && (RpFun < MaxPorts)) &&
+ !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2) && (RpFun < 8) && (RpFun + 8 < MaxPorts)) &&
+ !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3) && (RpFun < 8) && (RpFun + 16 < MaxPorts)) ) {
+ DEBUG ((DEBUG_ERROR, "GetPchPcieRpNumber invalid RpDev %x RpFun %x", RpDev, RpFun));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < mPchPcieControllerInfoSize; Index++) {
+ if (mPchPcieControllerInfo[Index].DevNum == RpDev) {
+ PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_PCH_PCR_SPX_PCD, &PciePcd);
+ for (FuncIndex = 0; FuncIndex < 4; FuncIndex ++) {
+ if (RpFun == ((PciePcd >> (FuncIndex * S_PCH_PCR_SPX_PCD_RP_FIELD)) & B_PCH_PCR_SPX_PCD_RP1FN)) {
+ break;
+ }
+ }
+ if (FuncIndex < 4) {
+ *RpNumber = mPchPcieControllerInfo[Index].RpNumBase + FuncIndex;
+ break;
+ }
+ }
+ }
+ if (Index >= mPchPcieControllerInfoSize) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+ @return PCIe port base address.
+**/
+UINTN
+PchPcieBase (
+ IN UINT32 RpIndex
+ )
+{
+ UINTN RpDevice;
+ UINTN RpFunction;
+ GetPchPcieRpDevFun (RpIndex, &RpDevice, &RpFunction);
+ return MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction);
+}
+
+/**
+ Determines whether L0s is supported on current stepping.
+
+ @return TRUE if L0s is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieL0sSupported (
+ VOID
+ )
+{
+ if (GetPchGeneration () == SklPch) {
+ if (GetPchSeries () == PchLp) {
+ if (PchStepping () < PchLpC0) {
+ return FALSE;
+ }
+ } else {
+ if (PchStepping () < PchHD0) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Some early SKL PCH steppings require Native ASPM to be disabled due to hardware issues:
+ - RxL0s exit causes recovery
+ - Disabling PCIe L0s capability disables L1
+ Use this function to determine affected steppings.
+
+ @return TRUE if Native ASPM is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieNativeAspmSupported (
+ VOID
+ )
+{
+ return PchIsPcieL0sSupported ();
+}
+
+/**
+ Check the RST PCIe Storage Cycle Router number according to the root port number and PCH type
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT32 The RST PCIe Storage Cycle Router Number
+**/
+UINT32
+RstGetCycleRouterNumber (
+ IN UINT32 RootPortNum
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (PchSeries == PchLp) {
+ if (RootPortNum < PCH_LP_PCIE_MAX_ROOT_PORTS) {
+ return mPchLpRstPcieStorageSupportedPort[RootPortNum];
+ }
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ if (RootPortNum < KBL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ return mKblPchHRstPcieStorageSupportedPort[RootPortNum];
+ }
+ } else {
+ if (RootPortNum < SKL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ return mSklPchHRstPcieStorageSupportedPort[RootPortNum];
+ }
+ }
+ }
+ return RST_PCIE_STORAGE_CR_INVALID;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf
new file mode 100644
index 0000000000..79ddb969ae
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH PCIE root port Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPcieRpLib
+FILE_GUID = B4129C2C-E0C5-4E04-A82A-C61D4F0B2C75
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPcieRpLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPcieRpLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
new file mode 100644
index 0000000000..e2585c36e0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
@@ -0,0 +1,458 @@
+/** @file
+ PCH PCR library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Read PCR register. (This is internal function)
+ It returns PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrRead (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrRead error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // @todo SKL PCH: check PID that not expected to use this routine, such as CAM_FLIS, CSME0
+ //
+
+ switch (Size) {
+ case 4:
+ *(UINT32*) OutData = MmioRead32 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 2:
+ *(UINT16*) OutData = MmioRead16 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 1:
+ *(UINT8*) OutData = MmioRead8 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ default:
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 4, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 2, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 1, (UINT32*) OutData);
+}
+
+BOOLEAN
+PchPcrWriteMmioCheck (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ //
+ // 1. USB2 AFE register must use SBI method
+ //
+
+ //
+ // 2. GPIO unlock register field must use SBI method
+ //
+ if (Pid == PID_GPIOCOM0) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM1) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM2) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM3) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ //
+ // 3. CIO2 FLIS regsiter must use SBI method
+ //
+
+ //
+ // 4. CSME0 based PCR should use the SBI method due to the FID requirement
+ //
+ if (Pid == PID_CSME0) {
+ return FALSE;
+ }
+ DEBUG_CODE_END ();
+ return TRUE;
+
+}
+
+/**
+ Write PCR register. (This is internal function)
+ It programs PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrWrite (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ IN UINT32 InData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_BEGIN ();
+ if (!PchPcrWriteMmioCheck (Pid, Offset)) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Pid: %x Offset: %x should access through SBI interface", Pid, Offset));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Write the PCR register with provided data
+ // Then read back PCR register to prevent from back to back write.
+ //
+ switch (Size) {
+ case 4:
+ MmioWrite32 (PCH_PCR_ADDRESS (Pid, Offset), (UINT32) InData);
+ break;
+ case 2:
+ MmioWrite16 (PCH_PCR_ADDRESS (Pid, Offset), (UINT16) InData);
+ break;
+ case 1:
+ MmioWrite8 (PCH_PCR_ADDRESS (Pid, Offset), (UINT8) InData);
+ break;
+ default:
+ break;
+ }
+ MmioRead32 (PCH_PCR_ADDRESS (PID_LPC, R_PCH_PCR_LPC_GCFD));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 4, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 2, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 1, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ Data32 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 4, &Data32);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data32 &= AndData;
+ Data32 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 4, Data32);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ Data16 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 2, (UINT32*) &Data16);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data16 &= AndData;
+ Data16 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 2, Data16);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+ Status = PchPcrRead (Pid, Offset, 1, (UINT32*) &Data8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data8 &= AndData;
+ Data8 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 1, Data8);
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
new file mode 100644
index 0000000000..fdc523143f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PCH PCR Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPcrLib
+FILE_GUID = 117C8D19-445B-46BF-B624-109F63709375
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPcrLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPcrLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c
new file mode 100644
index 0000000000..1985d5d133
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c
@@ -0,0 +1,136 @@
+/** @file
+ PCH PMC Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPmcLib.h>
+
+/**
+ Query PCH to determine the Pm Status
+ NOTE:
+ It's matter when did platform code use this library, since some status could be cleared by write one clear.
+ Therefore this funciton is not always return the same result in one boot.
+ It's suggested that platform code read this status in the beginning of post.
+ For the ColdBoot case, this function only returns one case of the cold boot. Some cold boot case might
+ depends on the power cycle scenario and should check with different condtion.
+
+ @param[in] PmStatus - The Pch Pm Status to be probed
+
+ @retval Return TRUE if Status querried is Valid or FALSE if otherwise
+**/
+BOOLEAN
+GetPchPmStatus (
+ PCH_PM_STATUS PmStatus
+ )
+{
+ UINTN PmcRegBase;
+ UINT32 PchPwrmBase;
+ UINT32 PmConA;
+ UINT32 PmConB;
+ UINT32 GblRst0;
+
+ PmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ PmConA = MmioRead32 (PmcRegBase + R_PCH_PMC_GEN_PMCON_A);
+ PmConB = MmioRead32 (PmcRegBase + R_PCH_PMC_GEN_PMCON_B);
+
+ GblRst0 = MmioRead32 (PchPwrmBase + R_PCH_PWRM_124);
+
+ switch (PmStatus) {
+ case WarmBoot:
+ if (PmConA & B_PCH_PMC_GEN_PMCON_A_MEM_SR) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlr:
+ if (PmConB & B_PCH_PMC_GEN_PMCON_B_PWR_FLR) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlrSys:
+ if (GblRst0 & BIT12) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlrPch:
+ if (GblRst0 & BIT11) {
+ return TRUE;
+ }
+ break;
+
+ case ColdBoot:
+ ///
+ /// Check following conditions for cold boot.
+ ///
+ if ((GblRst0 & BIT11) && // PCHPWR_FLR
+ (GblRst0 & BIT12) && // SYSPWR_FLR
+ (!(PmConA & B_PCH_PMC_GEN_PMCON_A_MEM_SR))) {
+ return TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/**
+ Funtion to check if Battery lost or CMOS cleared.
+
+ @reval TRUE Battery is always present.
+ @reval FALSE CMOS is cleared.
+**/
+BOOLEAN
+EFIAPI
+PchIsRtcBatteryGood (
+ VOID
+ )
+{
+ UINTN Data;
+ UINTN PmcBaseAddress;
+
+ //
+ // Check if the CMOS battery is present
+ // Checks RTC_PWR_STS bit in the GEN_PMCON_3 register
+ //
+ PmcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ Data = MmioRead32 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_B);
+
+ if ((Data & B_PCH_PMC_GEN_PMCON_B_RTC_PWR_STS) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf
new file mode 100644
index 0000000000..bd3a33ff70
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PEI/DXE/SMM PCH PMC Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPmcLib
+FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPmcLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPmcLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c
new file mode 100644
index 0000000000..08a28f7e6d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c
@@ -0,0 +1,448 @@
+/** @file
+ This file contains PSF routines
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPsfLib.h>
+#include <Library/PchInfoLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPchLpSerialIoPsfRegs[PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C0_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C1_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C2_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C3_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C4_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C5_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_SPI0_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_SPI1_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_UART0_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_UART1_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_UART2_REG_BASE
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPchHSerialIoPsfRegs[PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C0_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C1_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C2_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C3_REG_BASE,
+ 0,
+ 0,
+ R_PCH_H_PCR_PSF3_T0_SHDW_SPI0_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_SPI1_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_UART0_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_UART1_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_UART2_REG_BASE
+};
+
+/**
+ This procedure will enable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfEnableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 00b
+ // SerialIo device BAR is 64bit wide so to enable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be enabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32)~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS),
+ 0
+ );
+}
+
+/**
+ This procedure will disable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // SerialIo device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ This procedure will disable SerailIO device at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ This procedure will hide SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfHideSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will reveal SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfRevealSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS),
+ 0
+ );
+}
+
+/**
+ This procedure will set BARx value for TraceHub ACPI device at PSF level
+
+ @param[in] BarNum BAR Number (0:BAR0, 1:BAR1)
+ @param[in] BarValue 32bit BAR value
+
+ @retval None
+**/
+VOID
+PsfSetTraceHubAcpiDeviceBarValue (
+ IN UINT8 BarNum,
+ IN UINT32 BarValue
+ )
+{
+ UINT16 RegOffset;
+
+ if (BarNum > 1) {
+ ASSERT (FALSE);
+ }
+
+ RegOffset = R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_BAR0 + BarNum * 0x4;
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ RegOffset,
+ 0x0,
+ BarValue
+ );
+}
+
+/**
+ This procedure will enable MSE for TraceHub ACPI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnableTraceHubAcpiDeviceMemorySpace (
+ VOID
+ )
+{
+ PchPcrAndThenOr8 (
+ PID_PSF3, R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_MEMEN
+ );
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpHeciPsfRegBase[] =
+{
+ R_PCH_LP_PCR_PSF1_T0_SHDW_HECI1_REG_BASE,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_HECI2_REG_BASE,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_HECI3_REG_BASE
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHHeciPsfRegBase[] =
+{
+ R_PCH_H_PCR_PSF1_T0_SHDW_HECI1_REG_BASE,
+ R_PCH_H_PCR_PSF1_T0_SHDW_HECI2_REG_BASE,
+ R_PCH_H_PCR_PSF1_T0_SHDW_HECI3_REG_BASE
+};
+
+/**
+ Enable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfEnableHeciDevice (
+ IN UINT8 HeciDevice
+ )
+{
+ UINT16 *DevPsfBase;
+
+ if ((HeciDevice < 1) || (HeciDevice > 3)) {
+ ASSERT (FALSE);
+ }
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = mPchLpHeciPsfRegBase;
+ } else {
+ DevPsfBase = mPchHHeciPsfRegBase;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase[HeciDevice - 1] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS),
+ 0
+ );
+}
+
+/**
+ Disable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfDisableHeciDevice (
+ IN UINT8 HeciDevice
+ )
+{
+ UINT16 *DevPsfBase;
+
+ if ((HeciDevice < 1) || (HeciDevice > 3)) {
+ ASSERT (FALSE);
+ }
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = mPchLpHeciPsfRegBase;
+ } else {
+ DevPsfBase = mPchHHeciPsfRegBase;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase[HeciDevice - 1] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Enable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableIderDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS),
+ 0
+ );
+}
+
+/**
+ Disable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableIderDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Enable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableSolDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS),
+ 0
+ );
+}
+
+/**
+ Disable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableSolDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf
new file mode 100644
index 0000000000..941f5a72dd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for the PeiDxeSmmPchPsfLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPsfLib
+FILE_GUID = 36FE3C65-8367-46B9-9388-819C4933B899
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPsfLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PchInfoLib
+ PchPcrLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PchPsfLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
new file mode 100644
index 0000000000..9434b7f236
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
@@ -0,0 +1,385 @@
+/** @file
+ PCH SBI access library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchSbiAccessLib.h>
+
+/**
+ Execute PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecution (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ //
+ // Check address valid
+ //
+ if (((UINT32) Offset & 0x3) != 0) {
+ //
+ // Warning message for the address not DWORD alignment.
+ //
+ DEBUG ((DEBUG_INFO, "PchSbiExecution: Be careful that the address is not DWORD alignment.\n"));
+ }
+
+ return PchSbiExecutionEx ( Pid,
+ Offset,
+ Opcode,
+ Posted,
+ 0x000F,
+ 0x0000,
+ 0x0000,
+ Data32,
+ Response
+ );
+}
+
+/**
+ Full function for executing PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in] Fbe First byte enable
+ @param[in] Bar Bar
+ @param[in] Fid Function ID
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecutionEx (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ EFI_STATUS Status;
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ //
+ // Check opcode valid
+ //
+ switch (Opcode) {
+ case PciConfigRead:
+ case PciConfigWrite:
+ case PrivateControlRead:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ P2sbOrgStatus = FALSE;
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+ ///
+ /// BWG Section 2.2.1
+ /// 1. Poll P2SB PCI offset D8h[0] = 0b
+ /// Make sure the previous opeartion is completed.
+ ///
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto ExitPchSbiExecutionEx;
+ }
+ //
+ // Initial Response status
+ //
+ *Response = SBI_INVALID_RESPONSE;
+ Status = EFI_SUCCESS;
+ SbiStat = 0;
+ ///
+ /// 2. Write P2SB PCI offset D0h[31:0] with Address and Destination Port ID
+ ///
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR, (UINT32) ((Pid << 24) | (UINT16) Offset));
+ ///
+ /// 3. Write P2SB PCI offset DCh[31:0] with extended address, which is expected to be 0 in SKL PCH.
+ ///
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, (UINT32) RShiftU64 (Offset, 16));
+ ///
+ /// 5. Set P2SB PCI offset D8h[15:8] = 00000110b for read
+ /// Set P2SB PCI offset D8h[15:8] = 00000111b for write
+ //
+ // Set SBISTAT[15:8] to the opcode passed in
+ // Set SBISTAT[7] to the posted passed in
+ //
+ MmioAndThenOr16 (
+ (P2sbBase + R_PCH_P2SB_SBISTAT),
+ (UINT16) ~(B_PCH_P2SB_SBISTAT_OPCODE | B_PCH_P2SB_SBISTAT_POSTED),
+ (UINT16) ((Opcode << 8) | (Posted << 7))
+ );
+ ///
+ /// 6. Write P2SB PCI offset DAh[15:0] = F000h
+ ///
+ //
+ // Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
+ //
+ MmioWrite16 (
+ (P2sbBase + R_PCH_P2SB_SBIRID),
+ (((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF))
+ );
+
+ switch (Opcode) {
+ case PciConfigWrite:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with the intended data accordingly
+ ///
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), *Data32);
+ break;
+ default:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with dummy data such as 0,
+ /// because all D0-DFh register range must be touched in SKL PCH
+ /// for a successful SBI transaction.
+ ///
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), 0);
+ break;
+ }
+ ///
+ /// 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
+ ///
+ //
+ // Set SBISTAT[0] = 1b, trigger the SBI operation
+ //
+ MmioOr16 (P2sbBase + R_PCH_P2SB_SBISTAT, (UINT16) B_PCH_P2SB_SBISTAT_INITRDY);
+ //
+ // Poll SBISTAT[0] = 0b, Polling for Busy bit
+ //
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ //
+ // If timeout, it's fatal error.
+ //
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ ///
+ /// 8. Check if P2SB PCI offset D8h[2:1] = 00b for successful transaction
+ ///
+ *Response = (UINT8) ((SbiStat & B_PCH_P2SB_SBISTAT_RESPONSE) >> N_PCH_P2SB_SBISTAT_RESPONSE);
+ if (*Response == SBI_SUCCESSFUL) {
+ switch (Opcode) {
+ case PciConfigRead:
+ case PrivateControlRead:
+ ///
+ /// 9. Read P2SB PCI offset D4h[31:0] for SBI data
+ ///
+ *Data32 = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ break;
+ default:
+ break;
+ }
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ExitPchSbiExecutionEx:
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+ return Status;
+}
+
+/**
+ This function saves all PCH SBI registers.
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in, out] PchSbiRegister Structure for saving the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterSave (
+ IN OUT PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Save original SBI registers
+ //
+ PchSbiRegister->SbiAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIADDR);
+ PchSbiRegister->SbiExtAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR);
+ PchSbiRegister->SbiData = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ PchSbiRegister->SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ PchSbiRegister->SbiRid = MmioRead16 (P2sbBase + R_PCH_P2SB_SBIRID);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function restores all PCH SBI registers
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in] PchSbiRegister Structure for restoring the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterRestore (
+ IN PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Restore original SBI registers
+ //
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR , PchSbiRegister->SbiAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, PchSbiRegister->SbiExtAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIDATA , PchSbiRegister->SbiData);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBISTAT , PchSbiRegister->SbiStat);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBIRID , PchSbiRegister->SbiRid);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
new file mode 100644
index 0000000000..38ca8dce0e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PCH SBI access library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchSbiAccessLib
+FILE_GUID = 96ECB0FB-A975-4DC8-B88A-D90C3378CE87
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchSbiAccessLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchP2sbLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchSbiAccessLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
new file mode 100644
index 0000000000..7d24ed1269
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
@@ -0,0 +1,527 @@
+/** @file
+ PCH Serial IO Lib implementation.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchPsfLib.h>
+#include <Include/PcieRegs.h>
+
+typedef struct {
+ UINT32 Bar0;
+ UINT32 Bar1;
+} SERIAL_IO_CONTROLLER_DESCRIPTOR;
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 FuncNum;
+} SERIAL_IO_BDF_NUMBERS;
+
+typedef struct {
+ UINT16 PciDevIdPchLp;
+ UINT16 PciDevIdSklPchH;
+ UINT16 PciDevIdKblPchH;
+ CHAR8 AcpiHid[SERIALIO_HID_LENGTH];
+} SERIAL_IO_ID;
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_ID mSerialIoId [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {V_PCH_LP_SERIAL_IO_I2C0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID, "INT3442"},
+ {V_PCH_LP_SERIAL_IO_I2C1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID, "INT3443"},
+ {V_PCH_LP_SERIAL_IO_I2C2_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID, "INT3444"},
+ {V_PCH_LP_SERIAL_IO_I2C3_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID, "INT3445"},
+ {V_PCH_LP_SERIAL_IO_I2C4_DEVICE_ID, 0 , 0 , "INT3446"},
+ {V_PCH_LP_SERIAL_IO_I2C5_DEVICE_ID, 0 , 0 , "INT3447"},
+ {V_PCH_LP_SERIAL_IO_SPI0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID, "INT3440"},
+ {V_PCH_LP_SERIAL_IO_SPI1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID, "INT3441"},
+ {V_PCH_LP_SERIAL_IO_UART0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART0_DEVICE_ID, "INT3448"},
+ {V_PCH_LP_SERIAL_IO_UART1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART1_DEVICE_ID, "INT3449"},
+ {V_PCH_LP_SERIAL_IO_UART2_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART2_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART2_DEVICE_ID, "INT344A"}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_BDF_NUMBERS mSerialIoBdf [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoAcpiAddress [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x0000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x2000, PCH_SERIAL_IO_BASE_ADDRESS + 0x3000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x4000, PCH_SERIAL_IO_BASE_ADDRESS + 0x5000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x6000, PCH_SERIAL_IO_BASE_ADDRESS + 0x7000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x8000, PCH_SERIAL_IO_BASE_ADDRESS + 0x9000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xA000, PCH_SERIAL_IO_BASE_ADDRESS + 0xB000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xC000, PCH_SERIAL_IO_BASE_ADDRESS + 0xD000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xE000, PCH_SERIAL_IO_BASE_ADDRESS + 0xF000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x10000, PCH_SERIAL_IO_BASE_ADDRESS + 0x11000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x12000, PCH_SERIAL_IO_BASE_ADDRESS + 0x13000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x14000, PCH_SERIAL_IO_BASE_ADDRESS + 0x15000}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoPciCfgCtrAddr [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL1,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL2,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL3,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL4,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL5,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL6,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL13,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL14,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL9,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL10,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL11
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHSerialIoPciCfgCtrAddr[PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL1,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL2,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL3,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL4,
+ 0,
+ 0,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL13,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL14,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL9,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL10,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL11
+};
+
+
+/**
+ Returns index of the last i2c controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval Index of I2C controller
+**/
+PCH_SERIAL_IO_CONTROLLER
+GetMaxI2cNumber (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchH) {
+ return PchSerialIoIndexI2C3;
+ } else {
+ return PchSerialIoIndexI2C5;
+ }
+}
+
+/**
+ Returns string with AcpiHid assigned to selected SerialIo controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval pointer to 8-byte string
+**/
+CHAR8*
+GetSerialIoAcpiHID (
+ IN PCH_SERIAL_IO_CONTROLLER Number
+ )
+{
+ return mSerialIoId[Number].AcpiHid;
+}
+
+/**
+ Checks if Device with given PciDeviceId is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] PciDevId Device ID
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE Yes it is a SerialIo controller
+ @retval FALSE No it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoPciDevId (
+ IN UINT16 PciDevId,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Controller;
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+ for (Controller = 0; Controller < PCH_SERIALIO_MAX_CONTROLLERS; Controller++) {
+ if (((PchSeries == PchLp) && (PciDevId == mSerialIoId[Controller].PciDevIdPchLp)) ||
+ ((PchSeries == PchH) && (PchGen == SklPch) && (PciDevId == mSerialIoId[Controller].PciDevIdSklPchH)) ||
+ ((PchSeries == PchH) && (PchGen == KblPch) && (PciDevId == mSerialIoId[Controller].PciDevIdKblPchH))) {
+ *Number = Controller;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks if Device with given AcpiHid string is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] AcpiHid String
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE yes it is a SerialIo controller
+ @retval FALSE no it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoAcpiHid (
+ IN CHAR8 *AcpiHid,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Controller;
+ for (Controller = 0; Controller < PCH_SERIALIO_MAX_CONTROLLERS; Controller++) {
+ if (!AsciiStrCmp ((const CHAR8 *) AcpiHid, mSerialIoId[Controller].AcpiHid)) {
+ *Number = Controller;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Finds PCI Device Number of SerialIo devices.
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo device number
+**/
+UINT8
+GetSerialIoDeviceNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].DevNum;
+}
+
+/**
+ Finds PCI Function Number of SerialIo devices.
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo funciton number
+**/
+UINT8
+GetSerialIoFunctionNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].FuncNum;
+}
+
+/**
+ Finds BAR values of SerialIo devices.
+ SerialIo devices can be configured to not appear on PCI so traditional method of reading BAR might not work.
+ If the SerialIo device is in PCI mode, a request for BAR1 will return its PCI CFG space instead
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+ @param[in] BarNumber 0=BAR0, 1=BAR1
+
+ @retval SerialIo Bar value
+**/
+UINTN
+FindSerialIoBar (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice,
+ IN UINT8 BarNumber
+ )
+{
+ UINT64 Bar;
+ UINTN PcieBase;
+ UINT32 VenId;
+
+ PcieBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, GetSerialIoDeviceNumber (SerialIoDevice), GetSerialIoFunctionNumber (SerialIoDevice));
+ VenId = MmioRead32 (PcieBase + PCI_VENDOR_ID_OFFSET) & 0xFFFF;
+ if (VenId == V_PCH_INTEL_VENDOR_ID) {
+ if (BarNumber == 1) {
+ return PcieBase;
+ }
+ Bar = MmioRead32 (PcieBase + PCI_BASE_ADDRESSREG_OFFSET);
+ //
+ // For 64-Bit Memory Space BARs ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] & 0xFFFFFFFF) << 32)
+ //
+ if ((Bar & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) {
+ Bar = (Bar & 0xFFFFF000) + LShiftU64 (MmioRead32 (PcieBase + PCI_BASE_ADDRESSREG_OFFSET + 4) & 0xFFFFFFFF, 32);
+ return (UINTN) Bar;
+ }
+ return (UINTN) (Bar & 0xFFFFF000);
+ }
+ //
+ //PCI mode failed? Try hardcoded addresses from ACPI
+ //
+ if (BarNumber == 0) {
+ Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar0;
+ } else {
+ Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar1;
+ }
+ return (UINTN) Bar;
+}
+
+/**
+ Configures Serial IO Controller
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+**/
+VOID
+ConfigureSerialIoController (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode
+ )
+{
+ UINTN PciCfgBase;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 *SerialIoPciCfgCtrAddr;
+
+ if (Controller >= PchSerialIoIndexMax) {
+ return;
+ }
+
+ if (DeviceMode == PchSerialIoSkipInit) {
+ return;
+ }
+
+ PciCfgBase = MmPciBase (0, GetSerialIoDeviceNumber (Controller), GetSerialIoFunctionNumber (Controller));
+ //
+ // Do not modify a device that has already been disabled/hidden
+ //
+ if (MmioRead16 (PciCfgBase + PCI_VENDOR_ID_OFFSET) != V_PCH_INTEL_VENDOR_ID) {
+ return;
+ }
+
+ ///
+ /// Step 0. set Bit 16,17,18.
+ ///
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_D0I3MAXDEVPG, BIT18 | BIT17 | BIT16);
+
+ //
+ // special case for I2C4 and I2C5 on SPT-H
+ //
+ if (GetPchSeries () == PchH && (Controller == PchSerialIoIndexI2C4 || Controller == PchSerialIoIndexI2C5)) {
+ return;
+ }
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPciCfgCtrAddr = mPchLpSerialIoPciCfgCtrAddr;
+ } else {
+ SerialIoPciCfgCtrAddr = mPchHSerialIoPciCfgCtrAddr;
+ }
+
+ switch (DeviceMode) {
+ case PchSerialIoDisabled:
+ ///
+ /// Step 1. Put device in D3
+ /// Step 2. Function Disable in PSF
+ ///
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_PME_CTRL_STS, BIT1 | BIT0);
+ PsfDisableSerialIoDevice (Controller);
+ break;
+
+ case PchSerialIoAcpi:
+ case PchSerialIoAcpiHidden:
+ case PchSerialIoLegacyUart:
+ ///
+ /// reenable BAR1 in case it was disabled earlier
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller],(UINT32) ~(B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS),0x0);
+ PsfEnableSerialIoDeviceBar1 (Controller);
+ ///
+ /// Step 1. Assign BAR0
+ /// Step 2. Assign BAR1
+ ///
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_LOW, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_HIGH, 0x0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR1_LOW, mSerialIoAcpiAddress[Controller].Bar1);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR1_HIGH, 0x0);
+ ///
+ /// Step 3. Set Memory space Enable
+ ///
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ ///
+ /// Step 4. Disable device's PciCfg and enable ACPI interrupts
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], 0xFFFFFFFF, (B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS | B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN));
+ ///
+ /// Step 5. Disable device's PciCfg in PSF
+ ///
+ PsfHideSerialIoDevice (Controller);
+ ///
+ /// get controller out of reset
+ ///
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+ break;
+ case PchSerialIoPci:
+ ///
+ /// reenable PciCfg in case it was disabled earlier
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], (UINT32) ~(B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS | B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN),0x0);
+ PsfRevealSerialIoDevice (Controller);
+ ///
+ /// Disable Bar1
+ /// Disable Bar1 in PSF
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], 0xFFFFFFFF, B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS);
+ PsfDisableSerialIoDeviceBar1 (Controller);
+ //
+ // Assign BAR0 and Set Memory space Enable
+ //
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_LOW, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_HIGH, 0x0);
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ ///
+ /// get controller out of reset
+ ///
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+ break;
+ default:
+ return;
+ }
+
+ ///
+ /// Step X. Program clock dividers for UARTs
+ /// Step Y. Enable Byte addressing for UARTs in legacy mode
+ ///
+ if (Controller >= PchSerialIoIndexUart0 && Controller <= PchSerialIoIndexUart2) {
+ MmioWrite32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_CLK,
+ (B_PCH_SERIAL_IO_PPR_CLK_UPDATE | (V_PCH_SERIAL_IO_PPR_CLK_N_DIV << 16) |
+ (V_PCH_SERIAL_IO_PPR_CLK_M_DIV << 1) | B_PCH_SERIAL_IO_PPR_CLK_EN )
+ );
+
+ Data32And = (UINT32) (~(B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0)));
+ Data32Or = 0x0;
+ if (DeviceMode == PchSerialIoLegacyUart) {
+ Data32Or = (B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0));
+ }
+ PchPcrAndThenOr32 (PID_SERIALIO, R_PCH_PCR_SERIAL_IO_GPPRVRW7,Data32And,Data32Or);
+ //
+ // Dummy read after setting any of GPPRVRW7.
+ // Required for UART 16550 8-bit Legacy mode to become active
+ //
+ MmioRead32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_CLK);
+ }
+ ///
+ /// Step Z. Program I2C SDA hold registers
+ ///
+ if (Controller >= PchSerialIoIndexI2C0 && Controller <= GetMaxI2cNumber ()) {
+ if (DeviceMode != PchSerialIoDisabled) {
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_I2C_SDA_HOLD, V_PCH_SERIAL_IO_I2C_SDA_HOLD_VALUE);
+ }
+ }
+
+}
+
+/**
+ Initializes GPIO pins used by SerialIo I2C devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] I2cVoltage Voltage selector
+**/
+VOID
+SerialIoI2cGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 I2cVoltage
+ )
+{
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+ GpioSetSerialIoI2cPinsIntoNativeMode (Controller);
+ if (I2cVoltage == PchSerialIoIs18V) {
+ GpioSetSerialIoI2CPinsTolerance (Controller, TRUE);
+ }
+}
+
+/**
+ Initializes GPIO pins used by SerialIo SPI devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] SpiCsPolarity Polarity selector
+**/
+VOID
+SerialIoSpiGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 SpiCsPolarity
+ )
+{
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+
+ //
+ // set Invert Frame Signal before enabling pins to ensure correct initial ChipSelect polarity
+ //
+ if (SpiCsPolarity == PchSerialIoCsActiveLow) {
+ MmioAnd32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SSCR1, (UINT32) ~(B_PCH_SERIAL_IO_SSCR1_IFS));
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE);
+ } else {
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SSCR1, B_PCH_SERIAL_IO_SSCR1_IFS);
+ MmioAnd32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, (UINT32) ~B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE);
+ }
+
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, B_PCH_SERIAL_IO_SPI_CS_CONTROL_MODE);
+ GpioSetSerialIoSpiPinsIntoNativeMode (Controller-PchSerialIoIndexSpi0);
+}
+
+/**
+ Initializes GPIO pins used by SerialIo devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] HardwareFlowControl Hardware flow control selector
+**/
+VOID
+SerialIoUartGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN BOOLEAN HardwareFlowControl
+ )
+{
+
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+ GpioSetSerialIoUartPinsIntoNativeMode (Controller-PchSerialIoIndexUart0, HardwareFlowControl);
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf
new file mode 100644
index 0000000000..28ee07ee15
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf
@@ -0,0 +1,45 @@
+## @file
+# Component description file for PEI/DXE/SMM PCH Serial IO Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchSerialIoLib
+FILE_GUID = 613A22A2-5736-40f8-909B-DF10EA389C72
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchSerialIoLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+GpioLib
+PchPcrLib
+PchPsfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiDxeSmmPchSerialIoLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf
new file mode 100644
index 0000000000..723ad14ced
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchWdtCommonLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiDxeSmmPchWdtCommonLib
+ FILE_GUID = 171F78D2-0A52-4692-8830-AB693791EA23
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchWdtCommonLib
+
+[Sources]
+ WdtCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c
new file mode 100644
index 0000000000..00a2fef78d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c
@@ -0,0 +1,225 @@
+/** @file
+ Library that contains common parts of WdtPei and WdtDxe. Not a standalone module.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/MmPciLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mAllowExpectedReset = 0;
+
+/**
+ Reads LPC bridge to get Watchdog Timer address
+
+
+ @retval UINT32 Watchdog's address
+**/
+UINT32
+WdtGetAddress (
+ VOID
+ )
+{
+ UINT32 Address;
+ UINT16 ABase;
+
+ PchAcpiBaseGet (&ABase);
+ Address = ABase + R_PCH_OC_WDT_CTL;
+
+ return Address;
+}
+
+/**
+ Reloads WDT with new timeout value and starts it. Also sets Unexpected Reset bit, which
+ causes the next reset to be treated as watchdog expiration - unless AllowKnownReset()
+ function was called too.
+
+ @param[in] TimeoutValue Time in seconds before WDT times out. Supported range = 1 - 1024.
+
+ @retval EFI_SUCCESS if everything's OK
+ @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong
+**/
+EFI_STATUS
+EFIAPI
+WdtReloadAndStart (
+ IN UINT32 TimeoutValue
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "\n(Wdt) ReloadAndStartTimer(%d)\n", TimeoutValue));
+
+ if ((TimeoutValue > B_PCH_OC_WDT_CTL_TOV_MASK) || (TimeoutValue == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Readback = IoRead32 (WdtGetAddress ());
+ Readback |= (B_PCH_OC_WDT_CTL_EN | B_PCH_OC_WDT_CTL_FORCE_ALL | B_PCH_OC_WDT_CTL_ICCSURV);
+ if (mAllowExpectedReset == 0) {
+ Readback |= B_PCH_OC_WDT_CTL_UNXP_RESET_STS;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ ///
+ /// In Debug mode, WDT will not be turned on. This is to prevent platform reboots triggered
+ /// by WDT expiration, which can be expected when processor is halted for debugging
+ ///
+ Readback &= ~(B_PCH_OC_WDT_CTL_EN | B_PCH_OC_WDT_CTL_FORCE_ALL | B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ DEBUG ((DEBUG_INFO, "(Wdt) Wdt disabled in Debug BIOS\n"));
+ DEBUG_CODE_END ();
+
+ Readback &= ~(B_PCH_OC_WDT_CTL_TOV_MASK);
+ Readback |= ((TimeoutValue - 1) & B_PCH_OC_WDT_CTL_TOV_MASK);
+ IoWrite32 (WdtGetAddress (), Readback);
+ Readback |= B_PCH_OC_WDT_CTL_RLD;
+ IoWrite32 (WdtGetAddress (), Readback);
+ return EFI_SUCCESS;
+}
+
+/**
+ Disables WDT timer.
+
+
+**/
+VOID
+EFIAPI
+WdtDisable (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) DisableTimer\n"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+ Readback &= ~(B_PCH_OC_WDT_CTL_EN | B_PCH_OC_WDT_CTL_FORCE_ALL | B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ IoWrite32 (WdtGetAddress (), Readback);
+}
+
+/**
+ Returns WDT failure status.
+
+
+ @retval V_PCH_OC_WDT_CTL_STATUS_FAILURE If there was WDT expiration or unexpected reset
+ @retval V_PCH_OC_WDT_CTL_STATUS_OK Otherwise
+**/
+UINT8
+EFIAPI
+WdtCheckStatus (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) CheckTimerStatus\n"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+ DEBUG ((DEBUG_INFO, "(Wdt) Readback = (%x)\n", Readback));
+
+ if (Readback & B_PCH_OC_WDT_CTL_FAILURE_STS) {
+ DEBUG ((DEBUG_INFO, "(Wdt) Status = FAILURE\n"));
+ return V_PCH_OC_WDT_CTL_STATUS_FAILURE;
+ } else {
+ return V_PCH_OC_WDT_CTL_STATUS_OK;
+ }
+}
+
+/**
+ Normally, each reboot performed while watchdog runs is considered a failure.
+ This function allows platform to perform expected reboots with WDT running,
+ without being interpreted as failures.
+ In DXE phase, it is enough to call this function any time before reset.
+ In PEI phase, between calling this function and performing reset, ReloadAndStart()
+ must not be called.
+
+
+**/
+VOID
+EFIAPI
+WdtAllowKnownReset (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) AllowKnownReset\n"));
+
+ mAllowExpectedReset = 1;
+
+ Readback = IoRead32 (WdtGetAddress ());
+ Readback &= ~(B_PCH_OC_WDT_CTL_UNXP_RESET_STS | B_PCH_OC_WDT_CTL_FORCE_ALL);
+ IoWrite32 (WdtGetAddress (), Readback);
+}
+
+/**
+ Returns information if WDT coverage for the duration of BIOS execution
+ was requested by an OS application
+
+
+ @retval TRUE if WDT was requested
+ @retval FALSE if WDT was not requested
+**/
+UINT8
+EFIAPI
+IsWdtRequired (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) IsWdtRequired"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+
+ if ((Readback & B_PCH_OC_WDT_CTL_AFTER_POST) != 0) {
+ DEBUG ((DEBUG_INFO, " - yes\n"));
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_INFO, " - no\n"));
+ return FALSE;
+ }
+
+}
+
+/**
+ Returns WDT enabled/disabled status.
+
+
+ @retval TRUE if WDT is enabled
+ @retval FALSE if WDT is disabled
+**/
+UINT8
+EFIAPI
+IsWdtEnabled (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) IsWdtEnabled"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+
+ if ((Readback & B_PCH_OC_WDT_CTL_EN) != 0) {
+ DEBUG ((DEBUG_INFO, " - yes\n"));
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_INFO, " - no\n"));
+ return FALSE;
+ }
+
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
new file mode 100644
index 0000000000..0996b02ea6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
@@ -0,0 +1,138 @@
+/** @file
+ The PEI Library Implements OcWdt Support.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/Wdt.h>
+#include <Library/PchWdtCommonLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/IoLib.h>
+
+static WDT_PPI mWdtPpi = {
+ WdtReloadAndStart,
+ WdtCheckStatus,
+ WdtDisable,
+ WdtAllowKnownReset,
+ IsWdtRequired,
+ IsWdtEnabled
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mInstallWdtPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gWdtPpiGuid,
+ &mWdtPpi
+};
+
+/**
+ Reads PCH registers to check if platform wakes from S3/S4
+
+ @retval TRUE if platfrom wakes from S3/S4
+ @retval FALSE otherwise
+**/
+BOOLEAN
+IsWakeFromS3S4 (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT16 SleepType;
+
+ PchAcpiBaseGet (&ABase);
+
+ if (IoRead16 (ABase + R_PCH_ACPI_PM1_STS) & B_PCH_ACPI_PM1_STS_WAK) {
+ SleepType = IoRead16 (ABase + R_PCH_ACPI_PM1_CNT) & B_PCH_ACPI_PM1_CNT_SLP_TYP;
+ if ((SleepType == V_PCH_ACPI_PM1_CNT_S3) || (SleepType == V_PCH_ACPI_PM1_CNT_S4)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check for unexpected reset.
+ If there was an unexpected reset, enforces WDT expiration.
+**/
+VOID
+OcWdtResetCheck (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+ DEBUG ((DEBUG_ERROR, "(WDT) OcWdtResetCheck\n"));
+
+ ///
+ /// If there was a WDT expiration, set Failure Status and clear timeout status bits
+ /// Timeout status bits are cleared by writing '1'
+ ///
+ if (Readback & (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS)) {
+ DEBUG ((DEBUG_ERROR, "(WDT) Expiration detected.\n", Readback));
+ Readback |= B_PCH_OC_WDT_CTL_FAILURE_STS;
+ Readback |= (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS);
+ Readback &= ~(B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ } else {
+ ///
+ /// If there was unexpected reset but no WDT expiration and no resume from S3/S4,
+ /// clear unexpected reset status and enforce expiration. This is to inform Firmware
+ /// which has no access to unexpected reset status bit, that something went wrong.
+ ///
+ if ((Readback & B_PCH_OC_WDT_CTL_UNXP_RESET_STS) && !IsWakeFromS3S4 ()) {
+#ifndef MDEPKG_NDEBUG
+ DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected and ignored.\n"));
+ Readback &= ~(B_PCH_OC_WDT_CTL_FAILURE_STS | B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ Readback |= (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS);
+#else
+ DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected. Enforcing Wdt expiration.\n"));
+ WdtReloadAndStart (1);
+ ///
+ /// wait for reboot caused by WDT expiration
+ ///
+ CpuDeadLoop ();
+#endif
+ } else {
+ ///
+ /// No WDT expiration and no unexpected reset - clear Failure status
+ ///
+ DEBUG ((DEBUG_INFO, "(WDT) Status OK.\n", Readback));
+ Readback &= ~(B_PCH_OC_WDT_CTL_FAILURE_STS);
+ Readback |= (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS);
+ }
+ }
+
+ IoWrite32 (WdtGetAddress (), Readback);
+}
+
+/**
+ This function install WDT PPI
+
+ @retval EFI_STATUS Results of the installation of the WDT PPI
+**/
+EFI_STATUS
+EFIAPI
+OcWdtInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesInstallPpi (&mInstallWdtPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf
new file mode 100644
index 0000000000..a2b8f71784
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Component Description File for OcWdt Support.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiOcWdtLib
+FILE_GUID = D5207C23-3632-4078-A671-3B5C364B2BDB
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = OcWdtLib
+
+
+[LibraryClasses]
+IoLib
+DebugLib
+PeiServicesLib
+PchWdtCommonLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiOcWdtLib.c
+
+
+[Ppis]
+gWdtPpiGuid ## PRODUCES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c
new file mode 100644
index 0000000000..fdde6803c3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c
@@ -0,0 +1,41 @@
+/** @file
+ The Null PEI Library Implements OcWdt Support.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Ppi/Wdt.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Check for unexpected reset.
+ If there was an unexpected reset, enforces WDT expiration.
+**/
+VOID
+OcWdtResetCheck (
+ VOID
+ )
+{
+}
+
+/**
+ This function install WDT PPI
+
+ @retval EFI_STATUS Results of the installation of the WDT PPI
+**/
+EFI_STATUS
+EFIAPI
+OcWdtInit (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf
new file mode 100644
index 0000000000..93c951d49c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf
@@ -0,0 +1,32 @@
+## @file
+# Component Description File for OcWdt Support.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiOcWdtLib
+FILE_GUID = DB65B36B-E276-4A2b-AB20-61764889E483
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = OcWdtLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiOcWdtLibNull.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c
new file mode 100644
index 0000000000..650d414247
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c
@@ -0,0 +1,311 @@
+/** @file
+ Print whole PCH_PREMEM_POLICY_PPI
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiPchPolicyLibrary.h"
+
+/**
+ Print PCH_GENERAL_PREMEM_CONFIG and serial out.
+
+ @param[in] PchGeneralPreMemConfig Pointer to a PCH_GENERAL_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintGeneralPreMemConfig (
+ IN CONST PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH General PreMem Config -----------\n"));
+ DEBUG ((DEBUG_INFO, " AcpiBase= %x\n", PchGeneralPreMemConfig->AcpiBase));
+ DEBUG ((DEBUG_INFO, " Port80Route= %x\n", PchGeneralPreMemConfig->Port80Route));
+}
+
+/**
+ Print PCH_DCI_PREMEM_CONFIG and serial out.
+
+ @param[in] DciPreMemConfig Pointer to a PCH_DCI_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintDciPreMemConfig (
+ IN CONST PCH_DCI_PREMEM_CONFIG *DciPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH DCI PreMem Config ---------------\n"));
+ DEBUG ((DEBUG_INFO, "DciEn= %x\n", DciPreMemConfig->DciEn));
+}
+
+/**
+ Print PCH_WDT_PREMEM_CONFIG and serial out.
+
+ @param[in] WdtPreMemConfig Pointer to a PCH_WDT_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintWdtPreMemConfig (
+ IN CONST PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH WDT PreMem Config ---------------\n"));
+ DEBUG ((DEBUG_INFO, "DisableAndLock= %x\n", WdtPreMemConfig->DisableAndLock));
+}
+
+/**
+ Print PCH_TRACE_HUB_CONFIG and serial out.
+
+ @param[in] TraceHubConfig Pointer to a PCH_TRACE_HUB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintTraceHubPreMemConfig (
+ IN CONST PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH TraceHub PreMem Config ----------\n"));
+ DEBUG ((DEBUG_INFO, "EnableMode= %x\n", TraceHubPreMemConfig->EnableMode));
+ DEBUG ((DEBUG_INFO, "MemReg0Size= %x\n", TraceHubPreMemConfig->MemReg0Size));
+ DEBUG ((DEBUG_INFO, "MemReg1Size= %x\n", TraceHubPreMemConfig->MemReg1Size));
+}
+
+/**
+ Print PCH_HPET_PREMEM_CONFIG and serial out.
+
+ @param[in] HpetPreMemConfig Pointer to a PCH_HPET_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHpetPreMemConfig (
+ IN CONST PCH_HPET_PREMEM_CONFIG *HpetPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH HPET PreMem Config --------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable %x\n", HpetPreMemConfig->Enable));
+ DEBUG ((DEBUG_INFO, " BdfValid %x\n", HpetPreMemConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber %x\n", HpetPreMemConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber %x\n", HpetPreMemConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber %x\n", HpetPreMemConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " Base %x\n", HpetPreMemConfig->Base));
+}
+
+/**
+ Print PCH_SMBUS_CONFIG and serial out.
+
+ @param[in] SmbusConfig Pointer to a PCH_SMBUS_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSmbusPreMemConfig (
+ IN CONST PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH SMBUS PreMem Config -------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", SmbusPreMemConfig->Enable));
+ DEBUG ((DEBUG_INFO, " ArpEnable= %x\n", SmbusPreMemConfig->ArpEnable));
+ DEBUG ((DEBUG_INFO, " DynamicPowerGating= %x\n", SmbusPreMemConfig->DynamicPowerGating));
+ DEBUG ((DEBUG_INFO, " SpdWriteDisable= %x\n", SmbusPreMemConfig->SpdWriteDisable));
+ DEBUG ((DEBUG_INFO, " SmbusIoBase= %x\n", SmbusPreMemConfig->SmbusIoBase));
+ DEBUG ((DEBUG_INFO, " NumRsvdSmbusAddresses= %x\n", SmbusPreMemConfig->NumRsvdSmbusAddresses));
+ DEBUG ((DEBUG_INFO, " RsvdSmbusAddressTable= {"));
+ for (Index = 0; Index < SmbusPreMemConfig->NumRsvdSmbusAddresses; ++Index) {
+ DEBUG ((DEBUG_INFO, " %02xh", SmbusPreMemConfig->RsvdSmbusAddressTable[Index]));
+ }
+ DEBUG ((DEBUG_INFO, " }\n"));
+}
+
+/**
+ Print PCH_LPC_PREMEM_CONFIG and serial out.
+
+ @param[in] LpcPreMemConfig Pointer to a PCH_LPC_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLpcPreMemConfig (
+ IN CONST PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LPC PreMem Config ---------------\n"));
+ DEBUG ((DEBUG_INFO, "EnhancePort8xhDecoding= %x\n", LpcPreMemConfig->EnhancePort8xhDecoding));
+}
+
+/**
+ Print PCH_HSIO_PCIE_PREMEM_CONFIG and serial out.
+
+ @param[in] HsioPciePreMemConfig Pointer to a PCH_HSIO_PCIE_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHsioPciePreMemConfig (
+ IN CONST PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ HSIO PCIE PreMem Config -------------\n"));
+ DEBUG ((DEBUG_INFO, " PciePllSsc = %x\n", HsioPciePreMemConfig->PciePllSsc));
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioRxSetCtleEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioRxSetCtleEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioRxSetCtle= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioRxSetCtle));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen3DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen3DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DeEmphEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DeEmph= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmph));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph3p5Enable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5Enable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph3p5= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph6p0Enable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0Enable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph6p0= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0));
+ }
+}
+
+/**
+ Print PCH_HSIO_SATA_PREMEM_CONFIG and serial out.
+
+ @param[in] HsioSataPreMemConfig Pointer to a PCH_HSIO_SATA_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHsioSataPreMemConfig (
+ IN CONST PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ HSIO SATA PreMem Config -------------\n"));
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmph));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmph));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmph));
+ }
+}
+
+/**
+ Print PCH_HSIO_PREMEM_CONFIG and serial out.
+
+ @param[in] HsioPreMemConfig Pointer to a PCH_HSIO_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHsioPreMemConfig (
+ IN CONST PCH_HSIO_PREMEM_CONFIG *HsioPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ HSIO PreMem Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " ChipsetInitMessage : 0x%x\n", HsioPreMemConfig->ChipsetInitMessage));
+ DEBUG ((DEBUG_INFO, " BypassPhySyncReset : 0x%x\n", HsioPreMemConfig->BypassPhySyncReset));
+}
+
+/**
+ Print PCH_PCIE_RP_PREMEM_CONFIG and serial out.
+
+ @param[in] PcieRpPreMemConfig Pointer to a PCH_PCIE_RP_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPcieRpPreMemConfig (
+ IN CONST PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig
+ )
+{
+ UINT32 Index;
+ DEBUG ((DEBUG_INFO, "------------------ PCH PCIe RP PreMem Config -----------\n"));
+
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " Port[%d] RpEnabled= %x\n", Index, (PcieRpPreMemConfig->RpEnabledMask & (UINT32) (1 << Index)) != 0 ));
+ }
+}
+
+
+/**
+ Print whole PCH_POLICY_PPI and serial out.
+
+ @param[in] SiPreMemPolicyPpi The RC PREMEM Policy PPI instance
+
+**/
+VOID
+PchPreMemPrintPolicyPpi (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
+ PCH_DCI_PREMEM_CONFIG *DciPreMemConfig;
+ PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig;
+ PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig;
+ PCH_HPET_PREMEM_CONFIG *HpetPreMemConfig;
+ PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig;
+ PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig;
+ PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
+ PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
+ PCH_HSIO_PREMEM_CONFIG *HsioPreMemConfig;
+ PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPchGeneralPreMemConfigGuid, (VOID *) &PchGeneralPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gDciPreMemConfigGuid, (VOID *) &DciPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gWatchDogPreMemConfigGuid, (VOID *) &WdtPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gTraceHubPreMemConfigGuid, (VOID *) &TraceHubPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHpetPreMemConfigGuid, (VOID *) &HpetPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSmbusPreMemConfigGuid, (VOID *) &SmbusPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gLpcPreMemConfigGuid, (VOID *) &LpcPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioPciePreMemConfigGuid, (VOID *) &HsioPciePreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioSataPreMemConfigGuid, (VOID *) &HsioSataPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioPreMemConfigGuid, (VOID *) &HsioPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPcieRpPreMemConfigGuid, (VOID *) &PcieRpPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPreMemPolicyPpi->TableHeader.Header.Revision));
+
+ PchPrintGeneralPreMemConfig (PchGeneralPreMemConfig);
+ PchPrintDciPreMemConfig (DciPreMemConfig);
+ PchPrintWdtPreMemConfig (WdtPreMemConfig);
+ PchPrintTraceHubPreMemConfig (TraceHubPreMemConfig);
+ PchPrintHpetPreMemConfig (HpetPreMemConfig);
+ PchPrintSmbusPreMemConfig (SmbusPreMemConfig);
+ PchPrintLpcPreMemConfig (LpcPreMemConfig);
+ PchPrintHsioPciePreMemConfig (HsioPciePreMemConfig);
+ PchPrintHsioSataPreMemConfig (HsioSataPreMemConfig);
+ PchPrintHsioPreMemConfig (HsioPreMemConfig);
+ PchPrintPcieRpPreMemConfig (PcieRpPreMemConfig);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy End --------------------------\n"));
+ DEBUG_CODE_END ();
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c
new file mode 100644
index 0000000000..13a8f9fbd6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c
@@ -0,0 +1,783 @@
+/** @file
+ Print whole PCH_POLICY_PPI
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiPchPolicyLibrary.h"
+
+/**
+ Print PCH_USB_CONFIG and serial out.
+
+ @param[in] UsbConfig Pointer to a PCH_USB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintUsbConfig (
+ IN CONST PCH_USB_CONFIG *UsbConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH USB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " DisableComplianceMode = %x\n", UsbConfig->DisableComplianceMode));
+ DEBUG ((DEBUG_INFO, " DelayPdoProgramming = %x\n", UsbConfig->DelayPdoProgramming));
+
+ for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Enabled = %x\n", Index, UsbConfig->PortUsb20[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].OverCurrentPin = OC%x\n", Index, UsbConfig->PortUsb20[Index].OverCurrentPin));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Petxiset = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Petxiset));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Txiset = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Txiset));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Predeemp = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Predeemp));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Pehalfbit = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Pehalfbit));
+ }
+
+ for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d] Enabled = %x\n", Index, UsbConfig->PortUsb30[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].OverCurrentPin = OC%x\n", Index, UsbConfig->PortUsb30[Index].OverCurrentPin));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmph = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDeEmph));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmphEnable = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmp = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmpEnable = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmpEnable));
+ }
+
+ DEBUG ((DEBUG_INFO, " XdciConfig.Enable = %x\n", UsbConfig->XdciConfig.Enable));
+
+ for (Index = 0; Index < PCH_XHCI_MAX_SSIC_PORT_COUNT; Index++) {
+ DEBUG ((DEBUG_INFO, " SsicPort[%d].Enable = %x\n", Index, UsbConfig->SsicConfig.SsicPort[Index].Enable));
+ }
+
+}
+
+/**
+ Print PCH_PCIE_CONFIG and serial out.
+
+ @param[in] PcieConfig Pointer to a PCH_PCIE_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPcieConfig (
+ IN CONST PCH_PCIE_CONFIG *PcieConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH PCIE Config ------------------\n"));
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HotPlug= %x\n", Index, PcieConfig->RootPort[Index].HotPlug));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PmSci= %x\n", Index, PcieConfig->RootPort[Index].PmSci));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ExtSync= %x\n", Index, PcieConfig->RootPort[Index].ExtSync));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqSupported= %x\n", Index, PcieConfig->RootPort[Index].ClkReqSupported));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqNumber= %x\n", Index, PcieConfig->RootPort[Index].ClkReqNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqDetect= %x\n", Index, PcieConfig->RootPort[Index].ClkReqDetect));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] UnsupportedRequestReport= %x\n", Index, PcieConfig->RootPort[Index].UnsupportedRequestReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] FatalErrorReport= %x\n", Index, PcieConfig->RootPort[Index].FatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NoFatalErrorReport= %x\n", Index, PcieConfig->RootPort[Index].NoFatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CorrectableErrorReport= %x\n", Index, PcieConfig->RootPort[Index].CorrectableErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnFatalError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnNonFatalError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnNonFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnCorrectableError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnCorrectableError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] MaxPayload= %x\n", Index, PcieConfig->RootPort[Index].MaxPayload));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AcsEnabled= %x\n", Index, PcieConfig->RootPort[Index].AcsEnabled));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AdvancedErrorReporting= %x\n", Index, PcieConfig->RootPort[Index].AdvancedErrorReporting));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] TransmitterHalfSwing= %x\n", Index, PcieConfig->RootPort[Index].TransmitterHalfSwing));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PcieSpeed= %x\n", Index, PcieConfig->RootPort[Index].PcieSpeed));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Gen3EqPh3Method= %x\n", Index, PcieConfig->RootPort[Index].Gen3EqPh3Method));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PhysicalSlotNumber= %x\n", Index, PcieConfig->RootPort[Index].PhysicalSlotNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CompletionTimeout= %x\n", Index, PcieConfig->RootPort[Index].CompletionTimeout));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Aspm= %x\n", Index, PcieConfig->RootPort[Index].Aspm));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] L1Substates= %x\n", Index, PcieConfig->RootPort[Index].L1Substates));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrEnable= %x\n", Index, PcieConfig->RootPort[Index].LtrEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrConfigLock= %x\n", Index, PcieConfig->RootPort[Index].LtrConfigLock));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxSnoopLatency= %x\n", Index, PcieConfig->RootPort[Index].LtrMaxSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxNoSnoopLatency= %x\n", Index, PcieConfig->RootPort[Index].LtrMaxNoSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMode= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMultiplier= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideValue= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMode= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMultiplier= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideValue= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ForceLtrOverride= %x\n", Index, PcieConfig->RootPort[Index].ForceLtrOverride));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] DetectTimeoutMs= %x\n", Index, PcieConfig->RootPort[Index].DetectTimeoutMs));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitScale= %x\n", Index, PcieConfig->RootPort[Index].SlotPowerLimitScale));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitValue= %x\n", Index, PcieConfig->RootPort[Index].SlotPowerLimitValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Uptp= %x\n", Index, PcieConfig->RootPort[Index].Uptp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Dptp= %x\n", Index, PcieConfig->RootPort[Index].Dptp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] EnableCpm= %x\n", Index, PcieConfig->RootPort[Index].EnableCpm));
+
+ }
+ for (Index = 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index++) {
+ DEBUG ((DEBUG_INFO, " SwEqCoeffCm[%d] = %x\n", Index, PcieConfig->SwEqCoeffList[Index].Cm));
+ DEBUG ((DEBUG_INFO, " SwEqCoeffCp[%d] = %x\n", Index, PcieConfig->SwEqCoeffList[Index].Cp));
+ }
+ DEBUG ((DEBUG_INFO, " EnablePort8xhDecode= %x\n", PcieConfig->EnablePort8xhDecode));
+ DEBUG ((DEBUG_INFO, " PchPciePort8xhDecodePortIndex= %x\n", PcieConfig->PchPciePort8xhDecodePortIndex));
+ DEBUG ((DEBUG_INFO, " DisableRootPortClockGating= %x\n", PcieConfig->DisableRootPortClockGating));
+ DEBUG ((DEBUG_INFO, " EnablePeerMemoryWrite= %x\n", PcieConfig->EnablePeerMemoryWrite));
+ DEBUG ((DEBUG_INFO, " AllowNoLtrIccPllShutdown= %x\n", PcieConfig->AllowNoLtrIccPllShutdown));
+ DEBUG ((DEBUG_INFO, " ComplianceTestMode= %x\n", PcieConfig->ComplianceTestMode));
+ DEBUG ((DEBUG_INFO, " RpFunctionSwap= %x\n", PcieConfig->RpFunctionSwap));
+ DEBUG ((DEBUG_INFO, " PcieDeviceOverrideTablePtr= %x\n", PcieConfig->PcieDeviceOverrideTablePtr));
+}
+
+/**
+ Print PCH_SATA_CONFIG and serial out.
+
+ @param[in] SataConfig Pointer to a PCH_SATA_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSataConfig (
+ IN CONST PCH_SATA_CONFIG *SataConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH SATA Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", SataConfig->Enable));
+ DEBUG ((DEBUG_INFO, " SataMode= %x\n", SataConfig->SataMode));
+
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] Enabled= %x\n", Index, SataConfig->PortSettings[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HotPlug= %x\n", Index, SataConfig->PortSettings[Index].HotPlug));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] InterlockSw= %x\n", Index, SataConfig->PortSettings[Index].InterlockSw));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] External= %x\n", Index, SataConfig->PortSettings[Index].External));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SpinUp= %x\n", Index, SataConfig->PortSettings[Index].SpinUp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SolidStateDrive= %x\n", Index, SataConfig->PortSettings[Index].SolidStateDrive));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DevSlp= %x\n", Index, SataConfig->PortSettings[Index].DevSlp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] EnableDitoConfig= %x\n", Index, SataConfig->PortSettings[Index].EnableDitoConfig));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DmVal= %x\n", Index, SataConfig->PortSettings[Index].DmVal));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DitoVal= %x\n", Index, SataConfig->PortSettings[Index].DitoVal));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] ZpOdd= %x\n", Index, SataConfig->PortSettings[Index].ZpOdd));
+ }
+
+ DEBUG ((DEBUG_INFO, " RaidAlternateId= %x\n", SataConfig->Rst.RaidAlternateId));
+ DEBUG ((DEBUG_INFO, " Raid0= %x\n", SataConfig->Rst.Raid0));
+ DEBUG ((DEBUG_INFO, " Raid1= %x\n", SataConfig->Rst.Raid1));
+ DEBUG ((DEBUG_INFO, " Raid10= %x\n", SataConfig->Rst.Raid10));
+ DEBUG ((DEBUG_INFO, " Raid5= %x\n", SataConfig->Rst.Raid5));
+ DEBUG ((DEBUG_INFO, " Irrt= %x\n", SataConfig->Rst.Irrt));
+ DEBUG ((DEBUG_INFO, " OromUiBanner= %x\n", SataConfig->Rst.OromUiBanner));
+ DEBUG ((DEBUG_INFO, " OromUiDelay= %x\n", SataConfig->Rst.OromUiDelay));
+ DEBUG ((DEBUG_INFO, " HddUnlock= %x\n", SataConfig->Rst.HddUnlock));
+ DEBUG ((DEBUG_INFO, " LedLocate= %x\n", SataConfig->Rst.LedLocate));
+ DEBUG ((DEBUG_INFO, " IrrtOnly= %x\n", SataConfig->Rst.IrrtOnly));
+ DEBUG ((DEBUG_INFO, " SmartStorage= %x\n", SataConfig->Rst.SmartStorage));
+ DEBUG ((DEBUG_INFO, " LegacyOrom= %x\n", SataConfig->Rst.LegacyOrom));
+ DEBUG ((DEBUG_INFO, " OptaneMemory= %x\n", SataConfig->Rst.OptaneMemory));
+
+ DEBUG ((DEBUG_INFO, " SpeedSupport= %x\n", SataConfig->SpeedLimit));
+ DEBUG ((DEBUG_INFO, " EsataSpeedLimit= %x\n", SataConfig->EsataSpeedLimit));
+ DEBUG ((DEBUG_INFO, " TestMode= %x\n", SataConfig->TestMode));
+ DEBUG ((DEBUG_INFO, " SalpSupport= %x\n", SataConfig->SalpSupport));
+ DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", SataConfig->PwrOptEnable));
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].Enable = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].Enable));
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].RstPcieStoragePort = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].RstPcieStoragePort));
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].DeviceResetDelay = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay));
+ }
+}
+
+/**
+ Print PCH_IOAPIC_CONFIG and serial out.
+
+ @param[in] IoApicConfig Pointer to a PCH_IOAPIC_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintIoApicConfig (
+ IN CONST PCH_IOAPIC_CONFIG *IoApicConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH IOAPIC Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " BdfValid= %x\n", IoApicConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber= %x\n", IoApicConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber= %x\n", IoApicConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber= %x\n", IoApicConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " IoApicEntry24_119= %x\n", IoApicConfig->IoApicEntry24_119));
+ DEBUG ((DEBUG_INFO, " Early8254ClockGatingEnable= %x\n", IoApicConfig->Early8254ClockGatingEnable));
+ DEBUG ((DEBUG_INFO, " IoApicId= %x\n", IoApicConfig->IoApicId));
+ DEBUG ((DEBUG_INFO, " ApicRangeSelect= %x\n", IoApicConfig->ApicRangeSelect));
+}
+
+/**
+ Print PCH_LOCK_DOWN_CONFIG and serial out.
+
+ @param[in] LockDownConfig Pointer to a PCH_LOCK_DOWN_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLockDownConfig (
+ IN CONST PCH_LOCK_DOWN_CONFIG *LockDownConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH Lock Down Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " GlobalSmi= %x\n", LockDownConfig->GlobalSmi));
+ DEBUG ((DEBUG_INFO, " BiosInterface= %x\n", LockDownConfig->BiosInterface));
+ DEBUG ((DEBUG_INFO, " RtcLock= %x\n", LockDownConfig->RtcLock));
+ DEBUG ((DEBUG_INFO, " BiosLock= %x\n", LockDownConfig->BiosLock));
+ DEBUG ((DEBUG_INFO, " SpiEiss= %x\n", LockDownConfig->SpiEiss));
+}
+
+/**
+ Print PCH_HDAUDIO_CONFIG and serial out.
+
+ @param[in] HdaConfig Pointer to a PCH_HDAUDIO_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHdAudioConfig (
+ IN CONST PCH_HDAUDIO_CONFIG *HdaConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH HD-Audio Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " HDA Enable = %x\n", HdaConfig->Enable));
+ DEBUG ((DEBUG_INFO, " DSP Enable = %x\n", HdaConfig->DspEnable));
+ DEBUG ((DEBUG_INFO, " DSP UAA Compliance = %x\n", HdaConfig->DspUaaCompliance));
+ DEBUG ((DEBUG_INFO, " iDisp Codec Disconnect = %x\n", HdaConfig->IDispCodecDisconnect));
+ DEBUG ((DEBUG_INFO, " Pme = %x\n", HdaConfig->Pme));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Ownership = %x\n", HdaConfig->IoBufferOwnership));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Voltage = %x\n", HdaConfig->IoBufferVoltage));
+ DEBUG ((DEBUG_INFO, " VC Type = %x\n", HdaConfig->VcType));
+ DEBUG ((DEBUG_INFO, " HD-A Link Frequency = %x\n", HdaConfig->HdAudioLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link Frequency = %x\n", HdaConfig->IDispLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link T-Mode = %x\n", HdaConfig->IDispLinkTmode));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint DMIC = %x\n", HdaConfig->DspEndpointDmic));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint I2S = %x\n", HdaConfig->DspEndpointI2s));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint BT = %x\n", HdaConfig->DspEndpointBluetooth));
+ DEBUG ((DEBUG_INFO, " DSP Feature Mask = %x\n", HdaConfig->DspFeatureMask));
+ DEBUG ((DEBUG_INFO, " ResetWaitTimer = %x\n", HdaConfig->ResetWaitTimer));
+ DEBUG ((DEBUG_INFO, " VerbTableEntryNum = %x\n", HdaConfig->VerbTableEntryNum));
+ DEBUG ((DEBUG_INFO, " VerbTablePtr = %x\n", HdaConfig->VerbTablePtr));
+}
+
+/**
+ Print PCH_PM_CONFIG and serial out.
+
+ @param[in] PmConfig Pointer to a PCH_PM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPmConfig (
+ IN CONST PCH_PM_CONFIG *PmConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH PM Config ------------------\n"));
+
+ DEBUG ((DEBUG_INFO, " WakeConfig PmeB0S5Dis = %x\n", PmConfig->WakeConfig.PmeB0S5Dis));
+ DEBUG ((DEBUG_INFO, " WakeConfig WolEnableOverride = %x\n", PmConfig->WakeConfig.WolEnableOverride));
+ DEBUG ((DEBUG_INFO, " WakeConfig LanWakeFromDeepSx = %x\n", PmConfig->WakeConfig.LanWakeFromDeepSx));
+ DEBUG ((DEBUG_INFO, " WakeConfig PcieWakeFromDeepSx = %x\n", PmConfig->WakeConfig.PcieWakeFromDeepSx));
+ DEBUG ((DEBUG_INFO, " WakeConfig WoWlanEnable = %x\n", PmConfig->WakeConfig.WoWlanEnable));
+ DEBUG ((DEBUG_INFO, " WakeConfig WoWlanDeepSxEnable = %x\n", PmConfig->WakeConfig.WoWlanDeepSxEnable));
+
+ DEBUG ((DEBUG_INFO, " PchDeepSxPol = %x\n", PmConfig->PchDeepSxPol));
+ DEBUG ((DEBUG_INFO, " PchSlpS3MinAssert = %x\n", PmConfig->PchSlpS3MinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpS4MinAssert = %x\n", PmConfig->PchSlpS4MinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpSusMinAssert = %x\n", PmConfig->PchSlpSusMinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpAMinAssert = %x\n", PmConfig->PchSlpAMinAssert));
+ DEBUG ((DEBUG_INFO, " LpcClockRun = %x\n", PmConfig->LpcClockRun));
+ DEBUG ((DEBUG_INFO, " SlpStrchSusUp = %x\n", PmConfig->SlpStrchSusUp));
+ DEBUG ((DEBUG_INFO, " SlpLanLowDc = %x\n", PmConfig->SlpLanLowDc));
+ DEBUG ((DEBUG_INFO, " PwrBtnOverridePeriod = %x\n", PmConfig->PwrBtnOverridePeriod));
+ DEBUG ((DEBUG_INFO, " DisableEnergyReport = %x\n", PmConfig->DisableEnergyReport));
+ DEBUG ((DEBUG_INFO, " DisableDsxAcPresentPulldown = %x\n", PmConfig->DisableDsxAcPresentPulldown));
+ DEBUG ((DEBUG_INFO, " PmcReadDisable = %x\n", PmConfig->PmcReadDisable));
+ DEBUG ((DEBUG_INFO, " PchPwrCycDur = %x\n", PmConfig->PchPwrCycDur));
+ DEBUG ((DEBUG_INFO, " DisableNativePowerButton = %x\n", PmConfig->DisableNativePowerButton));
+ DEBUG ((DEBUG_INFO, " SlpS0Enabled = %x\n", PmConfig->SlpS0Enable));
+ DEBUG ((DEBUG_INFO, " MeWakeSts = %x\n", PmConfig->MeWakeSts));
+ DEBUG ((DEBUG_INFO, " WolOvrWkSts = %x\n", PmConfig->WolOvrWkSts));
+ DEBUG ((DEBUG_INFO, " EnableTcoTimer = %x\n", PmConfig->EnableTcoTimer));
+ DEBUG ((DEBUG_INFO, " SlpS0VmEnable = %x\n", PmConfig->SlpS0VmEnable));
+
+}
+
+/**
+ Print PCH_DMI_CONFIG and serial out.
+
+ @param[in] DmiConfig Pointer to a PCH_DMI_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintDmiConfig (
+ IN CONST PCH_DMI_CONFIG *DmiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH DMI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " DmiAspm= %x\n", DmiConfig->DmiAspm));
+ DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", DmiConfig->PwrOptEnable));
+ DEBUG ((DEBUG_INFO, " LegacyIoLowLatency= %x\n", DmiConfig->LegacyIoLowLatency));
+
+}
+
+/**
+ Print PCH_LPC_SIRQ_CONFIG and serial out.
+
+ @param[in] SerialIrqConfig Pointer to a PCH_LPC_SIRQ_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSerialIrqConfig (
+ IN CONST PCH_LPC_SIRQ_CONFIG *SerialIrqConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LPC SIRQ Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SirqEnable= %x\n", SerialIrqConfig->SirqEnable));
+ DEBUG ((DEBUG_INFO, " SirqMode= %x\n", SerialIrqConfig->SirqMode));
+ DEBUG ((DEBUG_INFO, " StartFramePulse= %x\n", SerialIrqConfig->StartFramePulse));
+}
+
+/**
+ Print PCH_THERMAL_CONFIG and serial out.
+
+ @param[in] ThermalConfig Pointer to a PCH_THERMAL_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintThermalConfig (
+ IN CONST PCH_THERMAL_CONFIG *ThermalConfig
+ )
+{
+ UINTN Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Thermal Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " TsmicLock= %x\n", ThermalConfig->TsmicLock));
+ DEBUG ((DEBUG_INFO, " TTLevels T0Level %x centigrade degree\n", ThermalConfig->TTLevels.T0Level));
+ DEBUG ((DEBUG_INFO, " TTLevels T1Level %x centigrade degree\n", ThermalConfig->TTLevels.T1Level));
+ DEBUG ((DEBUG_INFO, " TTLevels T2Level %x centigrade degree\n", ThermalConfig->TTLevels.T2Level));
+ DEBUG ((DEBUG_INFO, " TTLevels TTEnable %x\n", ThermalConfig->TTLevels.TTEnable));
+ DEBUG ((DEBUG_INFO, " TTLevels TTState13Enable %x\n", ThermalConfig->TTLevels.TTState13Enable));
+ DEBUG ((DEBUG_INFO, " TTLevels TTLock %x\n", ThermalConfig->TTLevels.TTLock));
+ DEBUG ((DEBUG_INFO, " TTLevels SuggestedSetting %x\n", ThermalConfig->TTLevels.SuggestedSetting));
+ DEBUG ((DEBUG_INFO, " TTLevels PchCrossThrottling %x\n", ThermalConfig->TTLevels.PchCrossThrottling));
+
+ DEBUG ((DEBUG_INFO, " DmiHaAWC DmiTsawEn %x\n", ThermalConfig->DmiHaAWC.DmiTsawEn));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS0TW %x\n", ThermalConfig->DmiHaAWC.TS0TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS1TW %x\n", ThermalConfig->DmiHaAWC.TS1TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS2TW %x\n", ThermalConfig->DmiHaAWC.TS2TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS3TW %x\n", ThermalConfig->DmiHaAWC.TS3TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC SuggestedSetting %x\n", ThermalConfig->DmiHaAWC.SuggestedSetting));
+
+ DEBUG ((DEBUG_INFO, " SataTT P0T1M %x\n", ThermalConfig->SataTT.P0T1M));
+ DEBUG ((DEBUG_INFO, " SataTT P0T2M %x\n", ThermalConfig->SataTT.P0T2M));
+ DEBUG ((DEBUG_INFO, " SataTT P0T3M %x\n", ThermalConfig->SataTT.P0T3M));
+ DEBUG ((DEBUG_INFO, " SataTT P0TDisp %x\n", ThermalConfig->SataTT.P0TDisp));
+ DEBUG ((DEBUG_INFO, " SataTT P0Tinact %x\n", ThermalConfig->SataTT.P0Tinact));
+ DEBUG ((DEBUG_INFO, " SataTT P0TDispFinit %x\n", ThermalConfig->SataTT.P0TDispFinit));
+ DEBUG ((DEBUG_INFO, " SataTT P1T1M %x\n", ThermalConfig->SataTT.P1T1M));
+ DEBUG ((DEBUG_INFO, " SataTT P1T2M %x\n", ThermalConfig->SataTT.P1T2M));
+ DEBUG ((DEBUG_INFO, " SataTT P1T3M %x\n", ThermalConfig->SataTT.P1T3M));
+ DEBUG ((DEBUG_INFO, " SataTT P1TDisp %x\n", ThermalConfig->SataTT.P1TDisp));
+ DEBUG ((DEBUG_INFO, " SataTT P1Tinact %x\n", ThermalConfig->SataTT.P1Tinact));
+ DEBUG ((DEBUG_INFO, " SataTT P1TDispFinit %x\n", ThermalConfig->SataTT.P1TDispFinit));
+ DEBUG ((DEBUG_INFO, " SataTT SuggestedSetting %x\n", ThermalConfig->SataTT.SuggestedSetting));
+
+ DEBUG ((DEBUG_INFO, " MemoryThrottling Enable= %x\n", ThermalConfig->MemoryThrottling.Enable));
+ for (Index = 0; Index < MaxTsGpioPin; Index++) {
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PmsyncEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PmsyncEnable));
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting C0TransmitEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].C0TransmitEnable));
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PinSelection= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PinSelection));
+ }
+ DEBUG ((DEBUG_INFO, " PchHotLevel = %x\n", ThermalConfig->PchHotLevel));
+ DEBUG ((DEBUG_INFO, " ThermalDeviceEnable %x\n", ThermalConfig->ThermalDeviceEnable));
+}
+
+/**
+ Print PCH_GENERAL_CONFIG and serial out.
+
+ @param[in] PchGeneralConfig Pointer to a PCH_GENERAL_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintGeneralConfig (
+ IN CONST PCH_GENERAL_CONFIG *PchGeneralConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH General Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SubSystemVendorId= %x\n", PchGeneralConfig->SubSystemVendorId));
+ DEBUG ((DEBUG_INFO, " SubSystemId= %x\n", PchGeneralConfig->SubSystemId));
+ DEBUG ((DEBUG_INFO, " Crid= %x\n", PchGeneralConfig->Crid));
+}
+
+/**
+ Print PCH_LAN_CONFIG and serial out.
+
+ @param[in] LanConfig Pointer to a PCH_LAN_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLanConfig (
+ IN CONST PCH_LAN_CONFIG *LanConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LAN Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", LanConfig->Enable));
+ DEBUG ((DEBUG_INFO, " LtrEnable= %x\n", LanConfig->LtrEnable));
+ DEBUG ((DEBUG_INFO, " K1OffEnable= %x\n", LanConfig->K1OffEnable));
+ DEBUG ((DEBUG_INFO, " ClkReqSupported= %d\n", LanConfig->ClkReqSupported));
+ DEBUG ((DEBUG_INFO, " ClkReqNumber= %d\n", LanConfig->ClkReqNumber));
+}
+
+/**
+ Print PCH_SERIAL_IO_CONFIG and serial out.
+
+ @param[in] SerialIoConfig Pointer to a PCH_SERIAL_IO_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSerialIoConfig (
+ IN CONST PCH_SERIAL_IO_CONFIG *SerialIoConfig
+ )
+{
+ UINTN Index;
+#ifndef MDEPKG_NDEBUG
+ static CHAR16 DeviceName[11][5] = {L"I2C0",L"I2C1",L"I2C2",L"I2C3",L"I2C4",L"I2C5",L"SPI0",L"SPI1",L"UA00",L"UA01",L"UA02"};
+#endif
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Serial IO Config ------------------\n"));
+ DEBUG_CODE_BEGIN ();
+ for (Index=0; Index<PCH_SERIALIO_MAX_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " SerialIoController %s: Mode %x\n", DeviceName[Index], SerialIoConfig->DevMode[Index]));
+ }
+ DEBUG_CODE_END ();
+ DEBUG ((DEBUG_INFO, " Gpio= %x\n", SerialIoConfig->Gpio));
+ for (Index=0; Index<PCH_SERIALIO_MAX_I2C_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " I2cVoltage[%d] = %x\n", Index, SerialIoConfig->I2cVoltage[Index]));
+ }
+ for (Index=0; Index<PCH_SERIALIO_MAX_SPI_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " SpiCsPolarity[%d] = %x\n", Index, SerialIoConfig->SpiCsPolarity[Index]));
+ }
+ for (Index=0; Index<PCH_SERIALIO_MAX_UART_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " UartHwFlowCtrl[%d] = %x\n", Index, SerialIoConfig->UartHwFlowCtrl[Index]));
+ }
+ DEBUG ((DEBUG_INFO, " DebugUartNumber = %x\n", SerialIoConfig->DebugUartNumber));
+ DEBUG ((DEBUG_INFO, " EnableDebugUartAfterPost = %x\n", SerialIoConfig->EnableDebugUartAfterPost));
+}
+
+/**
+ Print PCH_INTERRUPT_CONFIG and serial out
+
+ @param[in] InterruptConfig Pointer to Interrupt Configuration structure
+
+**/
+VOID
+PchPrintInterruptConfig (
+ IN CONST PCH_INTERRUPT_CONFIG *InterruptConfig
+ )
+{
+ UINTN Index;
+ //
+ // Print interrupt information
+ //
+ DEBUG ((DEBUG_INFO, "------------------ PCH Interrupt Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Interrupt assignment:\n"));
+ DEBUG ((DEBUG_INFO, " Dxx:Fx INTx IRQ\n"));
+ for (Index = 0; Index < InterruptConfig->NumOfDevIntConfig; Index++) {
+ DEBUG ((DEBUG_INFO, " D%02d:F%d %d %03d\n",
+ InterruptConfig->DevIntConfig[Index].Device,
+ InterruptConfig->DevIntConfig[Index].Function,
+ InterruptConfig->DevIntConfig[Index].IntX,
+ InterruptConfig->DevIntConfig[Index].Irq));
+ }
+ DEBUG ((DEBUG_INFO, " Legacy PIC interrupt routing:\n"));
+ DEBUG ((DEBUG_INFO, " PIRQx IRQx\n"));
+ for (Index = 0; Index < PCH_MAX_PXRC_CONFIG; Index++) {
+ DEBUG ((DEBUG_INFO, " PIRQ%c -> IRQ%d\n", Index + 65, InterruptConfig->PxRcConfig[Index]));
+ }
+ DEBUG ((DEBUG_INFO, " Other interrupt configuration:\n"));
+ DEBUG ((DEBUG_INFO, " GpioIrqRoute= %d\n", InterruptConfig->GpioIrqRoute));
+ DEBUG ((DEBUG_INFO, " SciIrqSelect= %d\n", InterruptConfig->SciIrqSelect));
+ DEBUG ((DEBUG_INFO, " TcoIrqEnable= %d\n", InterruptConfig->TcoIrqEnable));
+ DEBUG ((DEBUG_INFO, " TcoIrqSelect= %d\n", InterruptConfig->TcoIrqSelect));
+}
+
+/**
+ Print PCH_SKYCAM_CIO2_CONFIG and serial out.
+
+ @param[in] Cio2Config Pointer to a PCH_SKYCAM_CIO2_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintCio2Config (
+ IN CONST PCH_CIO2_CONFIG *Cio2Config
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH CIO2 Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "DeviceEnable= %x\n", Cio2Config->DeviceEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortATermOvrEnable= %x\n", Cio2Config->SkyCamPortATermOvrEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortBTermOvrEnable= %x\n", Cio2Config->SkyCamPortBTermOvrEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortCTermOvrEnable= %x\n", Cio2Config->SkyCamPortCTermOvrEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortDTermOvrEnable= %x\n", Cio2Config->SkyCamPortDTermOvrEnable));
+ DEBUG ((DEBUG_INFO, "------------------ PCH CIO2 FLS Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "PortATrimEnable= %x\n", Cio2Config->PortATrimEnable));
+ DEBUG ((DEBUG_INFO, "PortBTrimEnable= %x\n", Cio2Config->PortBTrimEnable));
+ DEBUG ((DEBUG_INFO, "PortCTrimEnable= %x\n", Cio2Config->PortCTrimEnable));
+ DEBUG ((DEBUG_INFO, "PortDTrimEnable= %x\n", Cio2Config->PortDTrimEnable));
+ DEBUG ((DEBUG_INFO, "PortACtleEnable= %x\n", Cio2Config->PortACtleEnable));
+ DEBUG ((DEBUG_INFO, "PortBCtleEnable= %x\n", Cio2Config->PortBCtleEnable));
+ DEBUG ((DEBUG_INFO, "PortCDCtleEnable= %x\n", Cio2Config->PortCDCtleEnable));
+ DEBUG ((DEBUG_INFO, "PortACtleCapValue= %x\n", Cio2Config->PortACtleCapValue));
+ DEBUG ((DEBUG_INFO, "PortBCtleCapValue= %x\n", Cio2Config->PortBCtleCapValue));
+ DEBUG ((DEBUG_INFO, "PortCDCtleCapValue= %x\n", Cio2Config->PortCDCtleCapValue));
+ DEBUG ((DEBUG_INFO, "PortADataTrimValue= %x\n", Cio2Config->PortADataTrimValue));
+ DEBUG ((DEBUG_INFO, "PortBDataTrimValue= %x\n", Cio2Config->PortBDataTrimValue));
+ DEBUG ((DEBUG_INFO, "PortCDDataTrimValue= %x\n", Cio2Config->PortCDDataTrimValue));
+ DEBUG ((DEBUG_INFO, "PortACtleResValue= %x\n", Cio2Config->PortACtleResValue));
+ DEBUG ((DEBUG_INFO, "PortBCtleResValue= %x\n", Cio2Config->PortBCtleResValue));
+ DEBUG ((DEBUG_INFO, "PortCDCtleResValue= %x\n", Cio2Config->PortCDCtleResValue));
+ DEBUG ((DEBUG_INFO, "PortAClkTrimValue= %x\n", Cio2Config->PortAClkTrimValue));
+ DEBUG ((DEBUG_INFO, "PortBClkTrimValue= %x\n", Cio2Config->PortBClkTrimValue));
+ DEBUG ((DEBUG_INFO, "PortCClkTrimValue= %x\n", Cio2Config->PortCClkTrimValue));
+ DEBUG ((DEBUG_INFO, "PortDClkTrimValue= %x\n", Cio2Config->PortDClkTrimValue));
+}
+
+/**
+ Print PCH_PORT61H_SMM_CONFIG and serial out.
+
+ @param[in] Port61hSmmConfig Pointer to a PCH_PORT61H_SMM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPort61hSmmConfig (
+ IN CONST PCH_PORT61H_SMM_CONFIG *Port61hSmmConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH Port61 Smm Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "Enable= %x\n", Port61hSmmConfig->Enable));
+}
+
+/**
+ Print PCH_SCS_CONFIG and serial out.
+
+ @param[in] ScsConfig Pointer to a PCH_SCS_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintScsConfig (
+ IN CONST PCH_SCS_CONFIG *ScsConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH SCS Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " ScsEmmcEnabled = %x\n", ScsConfig->ScsEmmcEnabled));
+ DEBUG ((DEBUG_INFO, " ScsSdSwitch = %x\n", ScsConfig->ScsSdSwitch));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400Enabled = %x\n", ScsConfig->ScsEmmcHs400Enabled));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400TuningRequired = %x\n", ScsConfig->ScsEmmcHs400TuningRequired));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400DllDataValid = %x\n", ScsConfig->ScsEmmcHs400DllDataValid));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400RxStrobeDll1 = %x\n", ScsConfig->ScsEmmcHs400RxStrobeDll1));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400TxDataDll = %x\n", ScsConfig->ScsEmmcHs400TxDataDll));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400DriverStrength = %x\n", ScsConfig->ScsEmmcHs400DriverStrength));
+}
+
+/**
+ Print PCH_ISH_CONFIG and serial out.
+
+ @param[in] IshConfig Pointer to a PCH_ISH_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintIshConfig (
+ IN CONST PCH_ISH_CONFIG *IshConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH ISH Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " ISH Enabled = %x\n", IshConfig->Enable));
+ DEBUG ((DEBUG_INFO, " SPI GPIO Assigned = %x\n", IshConfig->SpiGpioAssign));
+ DEBUG ((DEBUG_INFO, " UART0 GPIO Assigned = %x\n", IshConfig->Uart0GpioAssign));
+ DEBUG ((DEBUG_INFO, " UART1 GPIO Assigned = %x\n", IshConfig->Uart1GpioAssign));
+ DEBUG ((DEBUG_INFO, " I2C0 GPIO Assigned = %x\n", IshConfig->I2c0GpioAssign));
+ DEBUG ((DEBUG_INFO, " I2C1 GPIO Assigned = %x\n", IshConfig->I2c1GpioAssign));
+ DEBUG ((DEBUG_INFO, " I2C2 GPIO Assigned = %x\n", IshConfig->I2c2GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_0 GPIO Assigned = %x\n", IshConfig->Gp0GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_1 GPIO Assigned = %x\n", IshConfig->Gp1GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_2 GPIO Assigned = %x\n", IshConfig->Gp2GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_3 GPIO Assigned = %x\n", IshConfig->Gp3GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_4 GPIO Assigned = %x\n", IshConfig->Gp4GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_5 GPIO Assigned = %x\n", IshConfig->Gp5GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_6 GPIO Assigned = %x\n", IshConfig->Gp6GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_7 GPIO Assigned = %x\n", IshConfig->Gp7GpioAssign));
+}
+
+/**
+ Print PCH_FLASH_PROTECTION_CONFIG and serial out.
+
+ @param[in] FlashProtectConfig Pointer to a PCH_FLASH_PROTECTION_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintFlashProtectionConfig (
+ IN CONST PCH_FLASH_PROTECTION_CONFIG *FlashProtectConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Flash Protection Config ------------------\n"));
+ for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) {
+ DEBUG ((DEBUG_INFO, " WriteProtectionEnable[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].WriteProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ReadProtectionEnable[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].ReadProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeLimit[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].ProtectedRangeLimit));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeBase[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].ProtectedRangeBase));
+ }
+}
+
+/**
+ Print PCH_P2SB_CONFIG and serial out.
+
+ @param[in] P2sbConfig Pointer to a PCH_P2SB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintP2sbConfig (
+ IN CONST PCH_P2SB_CONFIG *P2sbConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH P2SB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "SbiUnlock= %x\n", P2sbConfig->SbiUnlock));
+ DEBUG ((DEBUG_INFO, "SbAccessUnlock= %x\n", P2sbConfig->SbAccessUnlock));
+}
+
+/**
+ Print PCH_SPI_CONFIG and serial out.
+
+ @param[in] SpiConfig Pointer to a PCH_SPI_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSpiConfig (
+ IN CONST PCH_SPI_CONFIG *SpiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH SPI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "ShowSpiController= %x\n", SpiConfig->ShowSpiController));
+}
+
+/**
+ Print PCH_ESPI_CONFIG.
+
+ @param[in] EspiConfig Pointer to a PCH_ESPI_CONFIG that provides the eSPI setting
+
+**/
+VOID
+PchPrintEspiConfig (
+ IN CONST PCH_ESPI_CONFIG *EspiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH eSPI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " BME for Master and Slave Enabled %x\n", EspiConfig->BmeMasterSlaveEnabled));
+}
+
+/**
+ Print whole PCH config blocks and serial out.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+
+**/
+VOID
+PchPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ PCH_GENERAL_CONFIG *PchGeneralConfig;
+ PCH_PCIE_CONFIG *PcieRpConfig;
+ PCH_SATA_CONFIG *SataConfig;
+ PCH_IOAPIC_CONFIG *IoApicConfig;
+ PCH_CIO2_CONFIG *Cio2Config;
+ PCH_DMI_CONFIG *DmiConfig;
+ PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
+ PCH_HDAUDIO_CONFIG *HdAudioConfig;
+ PCH_INTERRUPT_CONFIG *InterruptConfig;
+ PCH_ISH_CONFIG *IshConfig;
+ PCH_LAN_CONFIG *LanConfig;
+ PCH_P2SB_CONFIG *P2sbConfig;
+ PCH_LOCK_DOWN_CONFIG *LockDownConfig;
+ PCH_PM_CONFIG *PmConfig;
+ PCH_PORT61H_SMM_CONFIG *Port61hConfig;
+ PCH_SCS_CONFIG *ScsConfig;
+ PCH_SERIAL_IO_CONFIG *SerialIoConfig;
+ PCH_LPC_SIRQ_CONFIG *SerialIrqConfig;
+ PCH_SPI_CONFIG *SpiConfig;
+ PCH_THERMAL_CONFIG *ThermalConfig;
+ PCH_USB_CONFIG *UsbConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPchGeneralConfigGuid, (VOID *) &PchGeneralConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSataConfigGuid, (VOID *) &SataConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIoApicConfigGuid, (VOID *) &IoApicConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCio2ConfigGuid, (VOID *) &Cio2Config);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gDmiConfigGuid, (VOID *) &DmiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gFlashProtectionConfigGuid, (VOID *) &FlashProtectionConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHdAudioConfigGuid, (VOID *) &HdAudioConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gInterruptConfigGuid, (VOID *) &InterruptConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIshConfigGuid, (VOID *) &IshConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLanConfigGuid, (VOID *) &LanConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gP2sbConfigGuid, (VOID *) &P2sbConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPmConfigGuid, (VOID *) &PmConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPort61ConfigGuid, (VOID *) &Port61hConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gScsConfigGuid, (VOID *) &ScsConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIoConfigGuid, (VOID *) &SerialIoConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIrqConfigGuid, (VOID *) &SerialIrqConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSpiConfigGuid, (VOID *) &SpiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gThermalConfigGuid, (VOID *) &ThermalConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gUsbConfigGuid, (VOID *) &UsbConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print Policy Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPolicyPpi->TableHeader.Header.Revision));
+
+ PchPrintGeneralConfig (PchGeneralConfig);
+ PchPrintPcieConfig (PcieRpConfig);
+ PchPrintSataConfig (SataConfig);
+ PchPrintUsbConfig (UsbConfig);
+ PchPrintIoApicConfig (IoApicConfig);
+ PchPrintHdAudioConfig (HdAudioConfig);
+ PchPrintLanConfig (LanConfig);
+ PchPrintLockDownConfig (LockDownConfig);
+ PchPrintThermalConfig (ThermalConfig);
+ PchPrintPmConfig (PmConfig);
+ PchPrintDmiConfig (DmiConfig);
+ PchPrintSerialIrqConfig (SerialIrqConfig);
+ PchPrintSerialIoConfig (SerialIoConfig);
+ PchPrintInterruptConfig (InterruptConfig);
+ PchPrintCio2Config (Cio2Config);
+ PchPrintPort61hSmmConfig (Port61hConfig);
+ PchPrintScsConfig (ScsConfig);
+ PchPrintIshConfig (IshConfig);
+ PchPrintFlashProtectionConfig (FlashProtectionConfig);
+ PchPrintP2sbConfig (P2sbConfig);
+ PchPrintSpiConfig (SpiConfig);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print Policy End --------------------------\n"));
+ DEBUG_CODE_END ();
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c
new file mode 100644
index 0000000000..4e57b72d6e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c
@@ -0,0 +1,223 @@
+/** @file
+ This file is to load sample board policy.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiPchPolicyLibrary.h"
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPolicy The pointer to SI Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePolicy (
+ IN SI_POLICY_PPI *SiPolicy
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ PCH_PCIE_CONFIG *PcieRpConfig;
+ PCH_IOAPIC_CONFIG *IoApicConfig;
+ PCH_CIO2_CONFIG *Cio2Config;
+ PCH_DMI_CONFIG *DmiConfig;
+ PCH_LAN_CONFIG *LanConfig;
+ PCH_LOCK_DOWN_CONFIG *LockDownConfig;
+ PCH_PM_CONFIG *PmConfig;
+ PCH_SCS_CONFIG *ScsConfig;
+ PCH_SERIAL_IO_CONFIG *SerialIoConfig;
+ PCH_THERMAL_CONFIG *ThermalConfig;
+ PCH_USB_CONFIG *UsbConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gIoApicConfigGuid, (VOID *) &IoApicConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gCio2ConfigGuid, (VOID *) &Cio2Config);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gDmiConfigGuid, (VOID *) &DmiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gLanConfigGuid, (VOID *) &LanConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPmConfigGuid, (VOID *) &PmConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gScsConfigGuid, (VOID *) &ScsConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gSerialIoConfigGuid, (VOID *) &SerialIoConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gThermalConfigGuid, (VOID *) &ThermalConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gUsbConfigGuid, (VOID *) &UsbConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // PCIE RP
+ //
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ PcieRpConfig->RootPort[Index].ClkReqDetect = TRUE;
+ PcieRpConfig->RootPort[Index].AdvancedErrorReporting = TRUE;
+ PcieRpConfig->RootPort[Index].Gen3EqPh3Method = PchPcieEqSoftware;
+ }
+
+ PcieRpConfig->RootPort[0].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[0].ClkReqNumber = 2;
+
+ PcieRpConfig->RootPort[4].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[4].ClkReqNumber = 3;
+
+ PcieRpConfig->RootPort[5].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[5].ClkReqNumber = 1;
+
+ PcieRpConfig->RootPort[8].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[8].ClkReqNumber = 5;
+
+ PcieRpConfig->RootPort[9].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[9].ClkReqNumber = 4;
+
+ //
+ // USB
+ //
+ UsbConfig->PortUsb20[0].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[0].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[0].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[0].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[1].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[1].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[1].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[1].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[2].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[2].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[2].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[2].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[3].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[3].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[3].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[3].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[4].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[4].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[4].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[4].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[5].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[5].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[5].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[5].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[6].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[6].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[6].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[6].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[7].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[7].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[7].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[7].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[8].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[8].Afe.Txiset = 5;
+ UsbConfig->PortUsb20[8].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[8].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[9].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[9].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[9].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[9].Afe.Pehalfbit = 1;
+
+ // OC Map for USB2 Ports
+ UsbConfig->PortUsb20[ 0].OverCurrentPin = PchUsbOverCurrentPin0;
+ UsbConfig->PortUsb20[ 1].OverCurrentPin = PchUsbOverCurrentPin2;
+ UsbConfig->PortUsb20[ 2].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 3].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 4].OverCurrentPin = PchUsbOverCurrentPin2;
+ UsbConfig->PortUsb20[ 5].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 6].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 7].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 8].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb20[ 9].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[10].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[11].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[12].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[13].OverCurrentPin = PchUsbOverCurrentPinSkip;
+
+ // OC Map for USB3 Ports
+ UsbConfig->PortUsb30[0].OverCurrentPin = PchUsbOverCurrentPin0;
+ UsbConfig->PortUsb30[1].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb30[2].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb30[3].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb30[4].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb30[5].OverCurrentPin = PchUsbOverCurrentPinSkip;
+
+ UsbConfig->SsicConfig.SsicPort[0].Enable = TRUE;
+ UsbConfig->SsicConfig.SsicPort[1].Enable = TRUE;
+
+ //
+ // IOAPIC
+ //
+ IoApicConfig->BdfValid = 1;
+ IoApicConfig->BusNumber = 0xF0;
+ IoApicConfig->DeviceNumber = 0x1F;
+ IoApicConfig->FunctionNumber = 0;
+
+ //
+ // LAN
+ //
+ LanConfig->K1OffEnable = TRUE;
+ LanConfig->ClkReqSupported = TRUE;
+ LanConfig->ClkReqNumber = 3;
+
+ //
+ // PM CONFIG
+ //
+ PmConfig->LpcClockRun = TRUE;
+
+ //
+ // DMI
+ //
+ DmiConfig->PwrOptEnable = TRUE;
+
+ //
+ // SERIALIO
+ //
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C0] = PchSerialIoPci;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C1] = PchSerialIoPci;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C2] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C3] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C4] = PchSerialIoAcpiHidden;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C5] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexSpi0] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexSpi1] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexUart0] = PchSerialIoPci;
+ SerialIoConfig->DevMode[PchSerialIoIndexUart1] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexUart2] = PchSerialIoLegacyUart;
+
+ SerialIoConfig->I2cVoltage[2] = 1;
+ SerialIoConfig->I2cVoltage[3] = 1;
+
+ SerialIoConfig->SpiCsPolarity[0] = 1;
+
+ SerialIoConfig->UartHwFlowCtrl[0] = 1;
+ SerialIoConfig->UartHwFlowCtrl[1] = 1;
+ SerialIoConfig->UartHwFlowCtrl[2] = 1;
+
+
+ //
+ // SCS
+ //
+ ScsConfig->ScsEmmcHs400Enabled = TRUE;
+ ScsConfig->ScsEmmcHs400TuningRequired = TRUE;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c
new file mode 100644
index 0000000000..fcefd76e8e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c
@@ -0,0 +1,80 @@
+/** @file
+ This file is to load sample board policy.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiPchPolicyLibrary.h"
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPreMemPolicy The pointer to SI PREMEM Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePreMemPolicy (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicy
+ )
+{
+ EFI_STATUS Status;
+ PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig;
+ PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
+ PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gTraceHubPreMemConfigGuid, (VOID *) &TraceHubPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioPciePreMemConfigGuid, (VOID *) &HsioPciePreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioSataPreMemConfigGuid, (VOID *) &HsioSataPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // TRACEHUB
+ //
+ TraceHubPreMemConfig->MemReg0Size = 0x100000; // 1MB
+ TraceHubPreMemConfig->MemReg1Size = 0x100000; // 1MB
+
+ //
+ // HSIO PCIE
+ //
+ HsioPciePreMemConfig->Lane[0].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[0].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[1].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[1].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[2].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[2].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[3].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[3].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[5].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[5].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[7].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[7].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[8].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[8].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[9].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[9].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[10].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[10].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[11].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[11].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->PciePllSsc = 0xFF;
+
+ //
+ // HSIO SATA
+ //
+ HsioSataPreMemConfig->PortLane[0].HsioRxGen3EqBoostMagEnable = TRUE;
+ HsioSataPreMemConfig->PortLane[0].HsioRxGen3EqBoostMag = 4;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen1DownscaleAmpEnable = TRUE;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen1DownscaleAmp = 0x2C;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen2DownscaleAmpEnable = 0;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen2DownscaleAmp = 0x38;
+
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c
new file mode 100644
index 0000000000..f0f9f33f71
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c
@@ -0,0 +1,892 @@
+/** @file
+ This file is PeiPchPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiPchPolicyLibrary.h"
+
+/**
+ mDevIntConfig[] table contains data on INTx and IRQ for each device.
+ IRQ value for devices which use ITSS INTx->PIRQx mapping need to be set in a way
+ that for each multifunctional Dxx:Fy same interrupt pins must map to the same IRQ.
+ Those IRQ values will be used to update ITSS.PIRx register.
+ In APIC relationship between PIRQs and IRQs is:
+ PIRQA -> IRQ16
+ PIRQB -> IRQ17
+ PIRQC -> IRQ18
+ PIRQD -> IRQ19
+ PIRQE -> IRQ20
+ PIRQF -> IRQ21
+ PIRQG -> IRQ22
+ PIRQH -> IRQ23
+
+ Devices which use INTx->PIRQy mapping are: cAVS(in PCI mode), SMBus, GbE, TraceHub, PCIe,
+ SATA, HECI, IDE-R, KT Redirection, xHCI, Thermal Subsystem, Camera IO Host Controller
+
+ PCI Express Root Ports mapping should be programmed only with values as in below table (D27/28/29)
+ otherwise _PRT methods in ACPI for RootPorts would require additional patching as
+ PCIe Endpoint Device Interrupt is further subjected to INTx to PIRQy Mapping
+
+ Configured IRQ values are not used if an OS chooses to be in PIC instead of APIC mode
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mDevIntConfig[] = {
+// {31, 0, PchNoInt, 0}, // LPC/eSPI Interface, doesn't use interrupts
+// {31, 1, PchNoInt, 0}, // P2SB, doesn't use interrupts
+// {31, 2, PchNoInt, 0}, // PMC , doesn't use interrupts
+ {31, 3, PchIntA, 16}, // cAVS(Audio, Voice, Speach), INTA is default, programmed in PciCfgSpace 3Dh
+ {31, 4, PchIntA, 16}, // SMBus Controller, no default value, programmed in PciCfgSpace 3Dh
+// {31, 5, PchNoInt, 0}, // SPI , doesn't use interrupts
+ {31, 6, PchIntA, 16}, // GbE Controller, INTA is default, programmed in PciCfgSpace 3Dh
+ {31, 7, PchIntA, 16}, // TraceHub, INTA is default, RO register
+ {30, 0, PchIntA, 20}, // SerialIo: UART #0, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[7]
+ {30, 1, PchIntB, 21}, // SerialIo: UART #1, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[8]
+ {30, 2, PchIntC, 22}, // SerialIo: SPI #0, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[10]
+ {30, 3, PchIntD, 23}, // SerialIo: SPI #1, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[11]
+ {30, 4, PchIntB, 21}, // SCS: eMMC (SKL PCH-LP Only)
+ {30, 5, PchIntC, 22}, // SCS: SDIO (SKL PCH-LP Only)
+ {30, 6, PchIntD, 23}, // SCS: SDCard (SKL PCH-LP Only)
+ {29, 0, PchIntA, 16}, // PCI Express Port 9, INT is default, programmed in PciCfgSpace + FCh
+ {29, 1, PchIntB, 17}, // PCI Express Port 10, INT is default, programmed in PciCfgSpace + FCh
+ {29, 2, PchIntC, 18}, // PCI Express Port 11, INT is default, programmed in PciCfgSpace + FCh
+ {29, 3, PchIntD, 19}, // PCI Express Port 12, INT is default, programmed in PciCfgSpace + FCh
+ {29, 4, PchIntA, 16}, // PCI Express Port 13 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {29, 5, PchIntB, 17}, // PCI Express Port 14 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {29, 6, PchIntC, 18}, // PCI Express Port 15 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {29, 7, PchIntD, 19}, // PCI Express Port 16 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {28, 0, PchIntA, 16}, // PCI Express Port 1, INT is default, programmed in PciCfgSpace + FCh
+ {28, 1, PchIntB, 17}, // PCI Express Port 2, INT is default, programmed in PciCfgSpace + FCh
+ {28, 2, PchIntC, 18}, // PCI Express Port 3, INT is default, programmed in PciCfgSpace + FCh
+ {28, 3, PchIntD, 19}, // PCI Express Port 4, INT is default, programmed in PciCfgSpace + FCh
+ {28, 4, PchIntA, 16}, // PCI Express Port 5, INT is default, programmed in PciCfgSpace + FCh
+ {28, 5, PchIntB, 17}, // PCI Express Port 6, INT is default, programmed in PciCfgSpace + FCh
+ {28, 6, PchIntC, 18}, // PCI Express Port 7, INT is default, programmed in PciCfgSpace + FCh
+ {28, 7, PchIntD, 19}, // PCI Express Port 8, INT is default, programmed in PciCfgSpace + FCh
+ {27, 0, PchIntA, 16}, // PCI Express Port 17 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 1, PchIntB, 17}, // PCI Express Port 18 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 2, PchIntC, 18}, // PCI Express Port 19 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 3, PchIntD, 19}, // PCI Express Port 20 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 4, PchIntA, 16}, // PCI Express Port 21 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 5, PchIntB, 17}, // PCI Express Port 22 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 6, PchIntC, 18}, // PCI Express Port 23 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 7, PchIntD, 19}, // PCI Express Port 24 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {25, 0, PchIntA, 32}, // SerialIo UART Controller #2, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[9]
+// {24, 0, 0, 0}, // Reserved (used by RST PCIe Storage Cycle Router)
+ {23, 0, PchIntA, 16}, // SATA Controller, INTA is default, programmed in PciCfgSpace + 3Dh
+ {22, 0, PchIntA, 16}, // CSME: HECI #1
+ {22, 1, PchIntB, 17}, // CSME: HECI #2
+ {22, 2, PchIntC, 18}, // CSME: IDE-Redirection (IDE-R)
+ {22, 3, PchIntD, 19}, // CSME: Keyboard and Text (KT) Redirection
+ {22, 4, PchIntA, 16}, // CSME: HECI #3
+// {22, 7, PchNoInt, 0}, // CSME: WLAN
+ {21, 0, PchIntA, 16}, // SerialIo I2C Controller #0, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[1]
+ {21, 1, PchIntB, 17}, // SerialIo I2C Controller #1, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[2]
+ {21, 2, PchIntC, 18}, // SerialIo I2C Controller #2, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[3]
+ {21, 3, PchIntD, 19}, // SerialIo I2C Controller #3, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[4]
+ {20, 0, PchIntA, 16}, // USB 3.0 xHCI Controller, no default value, programmed in PciCfgSpace 3Dh
+ {20, 1, PchIntB, 17}, // USB Device Controller (OTG)
+ {20, 2, PchIntC, 18}, // Thermal Subsystem
+ {20, 3, PchIntA, 16}, // Camera IO Host Controller
+// {20, 4, 0, 0}, // TraceHub Phantom (ACPI) Function
+ {19, 0, PchIntA, 20}, // Integrated Sensor Hub
+// {18, 0, PchNoInt, 0}, // CSME: KVMcc, doesn't use interrupts
+// {18, 1, PchNoInt, 0}, // CSME: Clink, doesn't use interrupts
+// {18, 2, PchNoInt, 0}, // CSME: PMT, doesn't use interrupts
+// {18, 3, 0, 0}, // CSME: CSE UMA
+// {18, 4, 0, 0} // CSME: fTPM DMA
+};
+
+//
+// mLpOnlyDevIntConfig[] table contains data on INTx and IRQ for devices that exist on SPT-LP but not on SPT-H.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mLpOnlyDevIntConfig[] = {
+ {25, 1, PchIntB, 33}, // SerialIo I2C Controller #5, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[6]
+ {25, 2, PchIntC, 34} // SerialIo I2C Controller #4, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[5]
+};
+/**
+ mPxRcConfig[] table contains data for 8259 routing (how PIRQx is mapped to IRQy).
+ This information is used by systems which choose to use legacy PIC
+ interrupt controller. Only IRQ3-7,9-12,14,15 are valid. Values from this table
+ will be programmed into ITSS.PxRC registers.
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPxRcConfig[] = {
+ 11, // PARC: PIRQA -> IRQ11
+ 10, // PBRC: PIRQB -> IRQ10
+ 11, // PCRC: PIRQC -> IRQ11
+ 11, // PDRC: PIRQD -> IRQ11
+ 11, // PERC: PIRQE -> IRQ11
+ 11, // PFRC: PIRQF -> IRQ11
+ 11, // PGRC: PIRQG -> IRQ11
+ 11 // PHRC: PIRQH -> IRQ11
+};
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPchGeneralConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_GENERAL_CONFIG *PchGeneralConfig;
+ PchGeneralConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Name = %g\n", &PchGeneralConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PchGeneralConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ PCH general configuration
+ ********************************/
+ //
+ // Default SVID SDID configuration
+ //
+ PchGeneralConfig->SubSystemVendorId = V_PCH_INTEL_VENDOR_ID;
+ PchGeneralConfig->SubSystemId = V_PCH_DEFAULT_SID;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPcieRpConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ UINTN PortIndex;
+ PCH_SERIES PchSeries;
+ PCH_PCIE_CONFIG *PcieRpConfig;
+
+ PcieRpConfig = ConfigBlockPointer;
+ PchSeries = GetPchSeries ();
+
+ DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Name = %g\n", &PcieRpConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PcieRpConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ PCI Express related settings
+ ********************************/
+ PcieRpConfig->RpFunctionSwap = TRUE;
+
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ PcieRpConfig->RootPort[PortIndex].Aspm = PchPcieAspmAutoConfig;
+ PcieRpConfig->RootPort[PortIndex].PmSci = TRUE;
+ PcieRpConfig->RootPort[PortIndex].AcsEnabled = TRUE;
+ PcieRpConfig->RootPort[PortIndex].MaxPayload = PchPcieMaxPayload256;
+ PcieRpConfig->RootPort[PortIndex].EnableHotplugSmi = TRUE;
+ PcieRpConfig->RootPort[PortIndex].PhysicalSlotNumber = (UINT8) PortIndex;
+ PcieRpConfig->RootPort[PortIndex].L1Substates = PchPcieL1SubstatesL1_1_2;
+ PcieRpConfig->RootPort[PortIndex].EnableCpm = TRUE;
+
+ //
+ // PCIe LTR Configuration.
+ //
+ PcieRpConfig->RootPort[PortIndex].LtrEnable = TRUE;
+ if (PchSeries == PchLp) {
+ PcieRpConfig->RootPort[PortIndex].LtrMaxSnoopLatency = 0x1003;
+ PcieRpConfig->RootPort[PortIndex].LtrMaxNoSnoopLatency = 0x1003;
+ }
+ if (PchSeries == PchH) {
+ PcieRpConfig->RootPort[PortIndex].LtrMaxSnoopLatency = 0x0846;
+ PcieRpConfig->RootPort[PortIndex].LtrMaxNoSnoopLatency = 0x0846;
+ }
+ PcieRpConfig->RootPort[PortIndex].SnoopLatencyOverrideMode = 2;
+ PcieRpConfig->RootPort[PortIndex].SnoopLatencyOverrideMultiplier = 2;
+ PcieRpConfig->RootPort[PortIndex].SnoopLatencyOverrideValue = 60;
+ PcieRpConfig->RootPort[PortIndex].NonSnoopLatencyOverrideMode = 2;
+ PcieRpConfig->RootPort[PortIndex].NonSnoopLatencyOverrideMultiplier = 2;
+ PcieRpConfig->RootPort[PortIndex].NonSnoopLatencyOverrideValue = 60;
+
+ PcieRpConfig->RootPort[PortIndex].Uptp = 5;
+ PcieRpConfig->RootPort[PortIndex].Dptp = 7;
+
+ PcieRpConfig->EqPh3LaneParam[PortIndex].Cm = 6;
+ PcieRpConfig->EqPh3LaneParam[PortIndex].Cp = 2;
+ }
+
+ PcieRpConfig->SwEqCoeffList[0].Cm = 6;
+ PcieRpConfig->SwEqCoeffList[0].Cp = 2;
+ PcieRpConfig->SwEqCoeffList[1].Cm = 4;
+ PcieRpConfig->SwEqCoeffList[1].Cp = 2;
+ PcieRpConfig->SwEqCoeffList[2].Cm = 8;
+ PcieRpConfig->SwEqCoeffList[2].Cp = 2;
+ PcieRpConfig->SwEqCoeffList[3].Cm = 2;
+ PcieRpConfig->SwEqCoeffList[3].Cp = 2;
+ PcieRpConfig->SwEqCoeffList[4].Cm = 10;
+ PcieRpConfig->SwEqCoeffList[4].Cp = 2;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadSataConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ UINTN PortIndex;
+ UINTN Index;
+ PCH_SATA_CONFIG *SataConfig;
+ SataConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Name = %g\n", &SataConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SataConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ SATA related settings
+ ********************************/
+ SataConfig->Enable = TRUE;
+ SataConfig->SalpSupport = TRUE;
+ SataConfig->SataMode = PchSataModeAhci;
+
+ for (PortIndex = 0; PortIndex < GetPchMaxSataPortNum (); PortIndex++) {
+ SataConfig->PortSettings[PortIndex].Enable = TRUE;
+ SataConfig->PortSettings[PortIndex].DmVal = 15;
+ SataConfig->PortSettings[PortIndex].DitoVal = 625;
+ }
+
+ SataConfig->Rst.Raid0 = TRUE;
+ SataConfig->Rst.Raid1 = TRUE;
+ SataConfig->Rst.Raid10 = TRUE;
+ SataConfig->Rst.Raid5 = TRUE;
+ SataConfig->Rst.Irrt = TRUE;
+ SataConfig->Rst.OromUiBanner = TRUE;
+ SataConfig->Rst.OromUiDelay = PchSataOromDelay2sec;
+ SataConfig->Rst.HddUnlock = TRUE;
+ SataConfig->Rst.LedLocate = TRUE;
+ SataConfig->Rst.IrrtOnly = TRUE;
+ SataConfig->Rst.SmartStorage = TRUE;
+ SataConfig->Rst.OptaneMemory = TRUE;
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay = 100;
+ }
+
+ SataConfig->PwrOptEnable = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadIoApicConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_IOAPIC_CONFIG *IoApicConfig;
+ IoApicConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Name = %g\n", &IoApicConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Header.HobLength = 0x%x\n", IoApicConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Io Apic configuration
+ ********************************/
+ IoApicConfig->IoApicId = 0x02;
+ IoApicConfig->IoApicEntry24_119 = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadCio2ConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_CIO2_CONFIG *Cio2Config;
+ Cio2Config = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "Cio2Config->Header.GuidHob.Name = %g\n", &Cio2Config->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "Cio2Config->Header.GuidHob.Header.HobLength = 0x%x\n", Cio2Config->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Initialize CIO2 Config and FLS config
+ ********************************/
+ Cio2Config->DeviceEnable = TRUE;
+ Cio2Config->PortATrimEnable = TRUE;
+ Cio2Config->PortBTrimEnable = TRUE;
+ Cio2Config->PortCTrimEnable = TRUE;
+ Cio2Config->PortDTrimEnable = TRUE;
+ Cio2Config->PortACtleEnable = TRUE;
+ Cio2Config->PortBCtleEnable = TRUE;
+ Cio2Config->PortCDCtleEnable = TRUE;
+ Cio2Config->PortACtleCapValue = 0xE;
+ Cio2Config->PortBCtleCapValue = 0xE;
+ Cio2Config->PortCDCtleCapValue = 0xE;
+ Cio2Config->PortACtleResValue = 0xD;
+ Cio2Config->PortBCtleResValue = 0xD;
+ Cio2Config->PortCDCtleResValue = 0xD;
+ Cio2Config->PortAClkTrimValue = 0xA;
+ Cio2Config->PortBClkTrimValue = 0xA;
+ Cio2Config->PortCClkTrimValue = 0x9;
+ Cio2Config->PortDClkTrimValue = 0xA;
+ Cio2Config->PortADataTrimValue = 0xBBBB;
+ Cio2Config->PortBDataTrimValue = 0xBBBB;
+ Cio2Config->PortCDDataTrimValue = 0xCCCC;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadDmiConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_DMI_CONFIG *DmiConfig;
+ DmiConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Name = %g\n", &DmiConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", DmiConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ DMI related settings
+ ********************************/
+ DmiConfig->DmiAspm = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadFlashProtectionConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
+ FlashProtectionConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Name = %g\n", &FlashProtectionConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Header.HobLength = 0x%x\n", FlashProtectionConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHdAudioConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HDAUDIO_CONFIG *HdaAudioConfig;
+ HdaAudioConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HdaAudioConfig->Header.GuidHob.Name = %g\n", &HdaAudioConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HdaAudioConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HdaAudioConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ HD-Audio configuration
+ ********************************/
+ HdaAudioConfig->Enable = PCH_HDAUDIO_AUTO;
+ HdaAudioConfig->DspEnable = TRUE;
+ HdaAudioConfig->HdAudioLinkFrequency = PchHdaLinkFreq24MHz;
+ HdaAudioConfig->IDispLinkFrequency = PchHdaLinkFreq96MHz;
+ HdaAudioConfig->ResetWaitTimer = 600; // Must be at least 521us (25 frames)
+ HdaAudioConfig->DspEndpointDmic = PchHdaDmic4chArray;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadInterruptConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ UINT8 IntConfigTableEntries;
+ PCH_INTERRUPT_CONFIG *InterruptConfig;
+ InterruptConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Name = %g\n", &InterruptConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Header.HobLength = 0x%x\n", InterruptConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Interrupt Configuration
+ ********************************/
+ IntConfigTableEntries = sizeof (mDevIntConfig) / sizeof (PCH_DEVICE_INTERRUPT_CONFIG);
+ ASSERT (IntConfigTableEntries <= PCH_MAX_DEVICE_INTERRUPT_CONFIG);
+ InterruptConfig->NumOfDevIntConfig = IntConfigTableEntries;
+ CopyMem (
+ InterruptConfig->DevIntConfig,
+ mDevIntConfig,
+ sizeof (mDevIntConfig)
+ );
+ if (GetPchSeries () == PchLp) {
+ CopyMem (
+ &(InterruptConfig->DevIntConfig[IntConfigTableEntries]),
+ mLpOnlyDevIntConfig,
+ sizeof (mLpOnlyDevIntConfig)
+ );
+ InterruptConfig->NumOfDevIntConfig += (sizeof (mLpOnlyDevIntConfig) / sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
+ }
+
+ ASSERT ((sizeof (mPxRcConfig) / sizeof (UINT8)) <= PCH_MAX_PXRC_CONFIG);
+ CopyMem (
+ InterruptConfig->PxRcConfig,
+ mPxRcConfig,
+ sizeof (mPxRcConfig)
+ );
+
+ InterruptConfig->GpioIrqRoute = 14;
+ InterruptConfig->SciIrqSelect = 9;
+ InterruptConfig->TcoIrqSelect = 9;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadIshConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_ISH_CONFIG *IshConfig;
+ IshConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Name = %g\n", &IshConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Header.HobLength = 0x%x\n", IshConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ ISH Configuration
+ ********************************/
+ IshConfig->Enable = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadLanConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_LAN_CONFIG *LanConfig;
+ LanConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Name = %g\n", &LanConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LanConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Lan configuration
+ ********************************/
+ LanConfig->Enable = TRUE;
+ LanConfig->LtrEnable = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadLockDownConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_LOCK_DOWN_CONFIG *LockDownConfig;
+ LockDownConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Name = %g\n", &LockDownConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LockDownConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Lockdown configuration
+ ********************************/
+ LockDownConfig->GlobalSmi = TRUE;
+ //
+ // PCH BIOS Spec Flash Security Recommendations,
+ // Intel strongly recommends that BIOS sets the BIOS Interface Lock Down bit. Enabling this bit
+ // will mitigate malicious software attempts to replace the system BIOS option ROM with its own code.
+ // Here we always enable this as a Policy.
+ //
+ LockDownConfig->BiosInterface = TRUE;
+ LockDownConfig->RtcLock = TRUE;
+
+ //
+ // Enable BIOS region lock in SPI
+ //
+ LockDownConfig->BiosLock = TRUE;
+ LockDownConfig->SpiEiss = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadP2sbConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_P2SB_CONFIG *P2sbConfig;
+ P2sbConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Name = %g\n", &P2sbConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Header.HobLength = 0x%x\n", P2sbConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPmConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_PM_CONFIG *PmConfig;
+ PmConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Name = %g\n", &PmConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PmConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ MiscPm Configuration
+ ********************************/
+ PmConfig->MeWakeSts = TRUE;
+ PmConfig->WolOvrWkSts = TRUE;
+
+ PmConfig->WakeConfig.WolEnableOverride = TRUE;
+ PmConfig->WakeConfig.LanWakeFromDeepSx = TRUE;
+
+ PmConfig->PchSlpS3MinAssert = PchSlpS350ms;
+ PmConfig->PchSlpS4MinAssert = PchSlpS44s;
+ PmConfig->PchSlpSusMinAssert = PchSlpSus4s;
+ PmConfig->PchSlpAMinAssert = PchSlpA2s;
+
+ PmConfig->PmcReadDisable = TRUE;
+ PmConfig->SlpLanLowDc = TRUE;
+ PmConfig->LpcClockRun = TRUE;
+ PmConfig->SlpS0Enable = TRUE;
+ PmConfig->SlpS0VmEnable = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPort61ConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_PORT61H_SMM_CONFIG *Port61Config;
+ Port61Config = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "Port61Config->Header.GuidHob.Name = %g\n", &Port61Config->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "Port61Config->Header.GuidHob.Header.HobLength = 0x%x\n", Port61Config->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Port 61h emulation
+ ********************************/
+ Port61Config->Enable = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadScsConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_SCS_CONFIG *ScsConfig;
+ ScsConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Name = %g\n", &ScsConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Header.HobLength = 0x%x\n", ScsConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ SCS Configuration
+ ********************************/
+ ScsConfig->ScsEmmcEnabled = TRUE;
+ ScsConfig->ScsSdSwitch = PchScsSdcardMode;
+ ScsConfig->ScsEmmcHs400DriverStrength = DriverStrength40Ohm;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadSerialIoConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ UINTN Index;
+ PCH_SERIAL_IO_CONFIG *SerialIoConfig;
+ SerialIoConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Name = %g\n", &SerialIoConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SerialIoConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ SerialIo Configuration
+ ********************************/
+ for (Index = 0; Index < PCH_SERIALIO_MAX_CONTROLLERS; Index++) {
+ SerialIoConfig->DevMode[Index] = PchSerialIoPci;
+ }
+ SerialIoConfig->Gpio = TRUE;
+ SerialIoConfig->DebugUartNumber = PcdGet8 (PcdSerialIoUartNumber);
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadSerialIrqConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_LPC_SIRQ_CONFIG *SerialIrqConfig;
+ SerialIrqConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Name = %g\n", &SerialIrqConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SerialIrqConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Serial IRQ Configuration
+ ********************************/
+ SerialIrqConfig->SirqEnable = TRUE;
+ SerialIrqConfig->SirqMode = PchQuietMode;
+ SerialIrqConfig->StartFramePulse = PchSfpw4Clk;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadSpiConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_SPI_CONFIG *SpiConfig;
+ SpiConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SpiConfig->Header.GuidHob.Name = %g\n", &SpiConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "SpiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SpiConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadThermalConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_THERMAL_CONFIG *ThermalConfig;
+ ThermalConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Name = %g\n", &ThermalConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Header.HobLength = 0x%x\n", ThermalConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Thermal configuration.
+ ********************************/
+ ThermalConfig->ThermalDeviceEnable = 1;
+ ThermalConfig->TsmicLock = TRUE;
+ ThermalConfig->TTLevels.SuggestedSetting = TRUE;
+ ThermalConfig->TTLevels.PchCrossThrottling = TRUE;
+ ThermalConfig->DmiHaAWC.SuggestedSetting = TRUE;
+ ThermalConfig->SataTT.SuggestedSetting = TRUE;
+ ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].PmsyncEnable = TRUE;
+ ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].C0TransmitEnable = TRUE;
+ ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].PmsyncEnable = TRUE;
+ ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].C0TransmitEnable = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadUsbConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ UINTN PortIndex;
+ PCH_USB_CONFIG *UsbConfig;
+ UsbConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Name = %g\n", &UsbConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Header.HobLength = 0x%x\n", UsbConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ USB related configuration
+ ********************************/
+ for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++) {
+ UsbConfig->PortUsb20[PortIndex].Enable = TRUE;
+ }
+
+ for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++) {
+ UsbConfig->PortUsb30[PortIndex].Enable = TRUE;
+ }
+ //
+ // USB Port Over Current Pins mapping, please set as per board layout.
+ // Default is PchUsbOverCurrentPin0(0)
+ //
+ UsbConfig->PortUsb20[ 2].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb20[ 3].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb20[ 4].OverCurrentPin = PchUsbOverCurrentPin2;
+ UsbConfig->PortUsb20[ 5].OverCurrentPin = PchUsbOverCurrentPin2;
+ UsbConfig->PortUsb20[ 6].OverCurrentPin = PchUsbOverCurrentPin3;
+ UsbConfig->PortUsb20[ 7].OverCurrentPin = PchUsbOverCurrentPin3;
+ UsbConfig->PortUsb20[ 8].OverCurrentPin = PchUsbOverCurrentPin4;
+ UsbConfig->PortUsb20[ 9].OverCurrentPin = PchUsbOverCurrentPin4;
+ UsbConfig->PortUsb20[10].OverCurrentPin = PchUsbOverCurrentPin5;
+ UsbConfig->PortUsb20[11].OverCurrentPin = PchUsbOverCurrentPin5;
+ UsbConfig->PortUsb20[12].OverCurrentPin = PchUsbOverCurrentPin6;
+ UsbConfig->PortUsb20[13].OverCurrentPin = PchUsbOverCurrentPin6;
+
+ UsbConfig->PortUsb30[2].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb30[3].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb30[4].OverCurrentPin = PchUsbOverCurrentPin2;
+ UsbConfig->PortUsb30[5].OverCurrentPin = PchUsbOverCurrentPin2;
+
+ //
+ // Default values of USB2 AFE settings.
+ //
+ for (PortIndex = 0; PortIndex < PCH_H_XHCI_MAX_USB2_PORTS; PortIndex++) {
+ UsbConfig->PortUsb20[PortIndex].Afe.Petxiset = 3;
+ UsbConfig->PortUsb20[PortIndex].Afe.Txiset = 2;
+ UsbConfig->PortUsb20[PortIndex].Afe.Predeemp = 1;
+ UsbConfig->PortUsb20[PortIndex].Afe.Pehalfbit = 1;
+ }
+
+ //
+ // Enable/Disable SSIC support in the setup menu
+ //
+ for (PortIndex = 0; PortIndex < PCH_XHCI_MAX_SSIC_PORT_COUNT; PortIndex++) {
+ UsbConfig->SsicConfig.SsicPort[PortIndex].Enable = FALSE;
+ }
+
+ //
+ // xDCI configuration
+ //
+ UsbConfig->XdciConfig.Enable = FALSE;
+}
+
+/**
+ Load Espi Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadEspiConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_ESPI_CONFIG *EspiConfig;
+ EspiConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Name = %g\n", &EspiConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", EspiConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ Espi configuration.
+ ********************************/
+ EspiConfig->BmeMasterSlaveEnabled = TRUE;
+}
+
+static COMPONENT_BLOCK_ENTRY mPchIpBlocks [] = {
+ {&gPchGeneralConfigGuid, sizeof (PCH_GENERAL_CONFIG), PCH_GENERAL_CONFIG_REVISION, LoadPchGeneralConfigDefault},
+ {&gPcieRpConfigGuid, sizeof (PCH_PCIE_CONFIG), PCIE_RP_CONFIG_REVISION, LoadPcieRpConfigDefault},
+ {&gSataConfigGuid, sizeof (PCH_SATA_CONFIG), SATA_CONFIG_REVISION, LoadSataConfigDefault},
+ {&gIoApicConfigGuid, sizeof (PCH_IOAPIC_CONFIG), IOAPIC_CONFIG_REVISION, LoadIoApicConfigDefault},
+ {&gCio2ConfigGuid, sizeof (PCH_CIO2_CONFIG), CIO2_CONFIG_REVISION, LoadCio2ConfigDefault},
+ {&gDmiConfigGuid, sizeof (PCH_DMI_CONFIG), DMI_CONFIG_REVISION, LoadDmiConfigDefault},
+ {&gFlashProtectionConfigGuid, sizeof (PCH_FLASH_PROTECTION_CONFIG), FLASH_PROTECTION_CONFIG_REVISION, LoadFlashProtectionConfigDefault},
+ {&gHdAudioConfigGuid, sizeof (PCH_HDAUDIO_CONFIG), HDAUDIO_CONFIG_REVISION, LoadHdAudioConfigDefault},
+ {&gInterruptConfigGuid, sizeof (PCH_INTERRUPT_CONFIG), INTERRUPT_CONFIG_REVISION, LoadInterruptConfigDefault},
+ {&gIshConfigGuid, sizeof (PCH_ISH_CONFIG), ISH_CONFIG_REVISION, LoadIshConfigDefault},
+ {&gLanConfigGuid, sizeof (PCH_LAN_CONFIG), LAN_CONFIG_REVISION, LoadLanConfigDefault},
+ {&gLockDownConfigGuid, sizeof (PCH_LOCK_DOWN_CONFIG), LOCK_DOWN_CONFIG_REVISION, LoadLockDownConfigDefault},
+ {&gP2sbConfigGuid, sizeof (PCH_P2SB_CONFIG), P2SB_CONFIG_REVISION, LoadP2sbConfigDefault},
+ {&gPmConfigGuid, sizeof (PCH_PM_CONFIG), PM_CONFIG_REVISION, LoadPmConfigDefault},
+ {&gPort61ConfigGuid, sizeof (PCH_PORT61H_SMM_CONFIG), PORT_61_CONFIG_REVISION, LoadPort61ConfigDefault},
+ {&gScsConfigGuid, sizeof (PCH_SCS_CONFIG), SCS_CONFIG_REVISION, LoadScsConfigDefault},
+ {&gSerialIoConfigGuid, sizeof (PCH_SERIAL_IO_CONFIG), SERIAL_IO_CONFIG_REVISION, LoadSerialIoConfigDefault},
+ {&gSerialIrqConfigGuid, sizeof (PCH_LPC_SIRQ_CONFIG), SERIAL_IRQ_CONFIG_REVISION, LoadSerialIrqConfigDefault},
+ {&gSpiConfigGuid, sizeof (PCH_SPI_CONFIG), SPI_CONFIG_REVISION, LoadSpiConfigDefault},
+ {&gThermalConfigGuid, sizeof (PCH_THERMAL_CONFIG), THERMAL_CONFIG_REVISION, LoadThermalConfigDefault},
+ {&gUsbConfigGuid, sizeof (PCH_USB_CONFIG), USB_CONFIG_REVISION, LoadUsbConfigDefault},
+ {&gEspiConfigGuid, sizeof (PCH_ESPI_CONFIG), ESPI_CONFIG_REVISION, LoadEspiConfigDefault}
+
+
+};
+
+/**
+ Get PCH config block table total size.
+
+ @retval Size of PCH config block table
+**/
+UINT16
+EFIAPI
+PchGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mPchIpBlocks[0], sizeof (mPchIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ PchAddConfigBlocks add all PCH config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add PCH config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+PchAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "PCH AddConfigBlocks\n"));
+
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchIpBlocks[0], sizeof (mPchIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf
new file mode 100644
index 0000000000..d4d4ac1e54
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf
@@ -0,0 +1,93 @@
+## @file
+# Component description file for the PeiPchPolicy libbrary.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiPchPolicyLib
+FILE_GUID = BB1AC992-B2CA-4744-84B7-915C185576C5
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PchPolicyLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+PcdLib
+PeiServicesLib
+BaseMemoryLib
+MemoryAllocationLib
+PchInfoLib
+ConfigBlockLib
+SiConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress
+gSiPkgTokenSpaceGuid.PcdSerialIoUartDebugEnable
+gSiPkgTokenSpaceGuid.PcdSerialIoUartNumber
+
+
+[Sources]
+PeiPchPolicyLib.c
+PeiPchPolicyLibrary.h
+PchPrintPolicy.c
+PchSamplePolicyLib.c
+PeiPchPreMemPolicyLib.c
+PchPreMemPrintPolicy.c
+PchSamplePreMemPolicyLib.c
+
+
+[Guids]
+gPchGeneralConfigGuid ## CONSUMES
+gPcieRpConfigGuid ## CONSUMES
+gSataConfigGuid ## CONSUMES
+gIoApicConfigGuid ## CONSUMES
+gCio2ConfigGuid ## CONSUMES
+gDmiConfigGuid ## CONSUMES
+gFlashProtectionConfigGuid ## CONSUMES
+gHdAudioConfigGuid ## CONSUMES
+gInterruptConfigGuid ## CONSUMES
+gIshConfigGuid ## CONSUMES
+gLanConfigGuid ## CONSUMES
+gLockDownConfigGuid ## CONSUMES
+gP2sbConfigGuid ## CONSUMES
+gPmConfigGuid ## CONSUMES
+gPort61ConfigGuid ## CONSUMES
+gScsConfigGuid ## CONSUMES
+gSerialIoConfigGuid ## CONSUMES
+gSerialIrqConfigGuid ## CONSUMES
+gSpiConfigGuid ## CONSUMES
+gEspiConfigGuid ## CONSUMES
+gThermalConfigGuid ## CONSUMES
+gUsbConfigGuid ## CONSUMES
+gPchGeneralPreMemConfigGuid ## COMSUMES
+gDciPreMemConfigGuid ## CONSUMES
+gWatchDogPreMemConfigGuid ## CONSUMES
+gTraceHubPreMemConfigGuid ## CONSUMES
+gHpetPreMemConfigGuid ## CONSUMES
+gSmbusPreMemConfigGuid ## CONSUMES
+gLpcPreMemConfigGuid ## CONSUMES
+gHsioPciePreMemConfigGuid ## CONSUMES
+gHsioSataPreMemConfigGuid ## CONSUMES
+gHsioPreMemConfigGuid ## CONSUMES
+gPcieRpPreMemConfigGuid ## CONSUMES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h
new file mode 100644
index 0000000000..9be618d38a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h
@@ -0,0 +1,32 @@
+/** @file
+ Header file for the PeiPchPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_PCH_POLICY_LIBRARY_H_
+#define _PEI_PCH_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/PchInfoLib.h>
+#include <Ppi/SiPolicy.h>
+#include <PchAccess.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchPolicyLib.h>
+
+#define PCH_HPET_BASE_ADDRESS 0xFED00000
+
+#endif // _PEI_PCH_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c
new file mode 100644
index 0000000000..5480cf3d5c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c
@@ -0,0 +1,306 @@
+/** @file
+ This file is PeiPchPreMemPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiPchPolicyLibrary.h"
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPchGeneralPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
+ PchGeneralPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Name = %g\n", &PchGeneralPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ PCH general premem configuration
+ ********************************/
+ //
+ // Default SVID SDID configuration
+ //
+ PchGeneralPreMemConfig->AcpiBase = PcdGet16 (PcdAcpiBaseAddress);
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadDciPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_DCI_PREMEM_CONFIG *DciPreMemConfig;
+ DciPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Name = %g\n", &DciPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", DciPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ DCI Configuration
+ ********************************/
+ DciPreMemConfig->DciAutoDetect = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadWatchDogPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig;
+ WdtPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Name = %g\n", &WdtPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", WdtPreMemConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadTraceHubPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig;
+ TraceHubPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "TraceHubPreMemConfig->Header.GuidHob.Name = %g\n", &TraceHubPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "TraceHubPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", TraceHubPreMemConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHpetPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HPET_PREMEM_CONFIG *HpetPreMemConfig;
+ HpetPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HpetPreMemConfig->Header.GuidHob.Name = %g\n", &HpetPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HpetPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HpetPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ HPET Configuration
+ ********************************/
+ HpetPreMemConfig->Enable = TRUE;
+ HpetPreMemConfig->Base = PCH_HPET_BASE_ADDRESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusRsvdAddresses[] = {
+ 0xA0,
+ 0xA2,
+ 0xA4,
+ 0xA6
+};
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadSmbusPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig;
+ SmbusPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Name = %g\n", &SmbusPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SmbusPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ SMBus configuration
+ ********************************/
+ SmbusPreMemConfig->Enable = TRUE;
+ SmbusPreMemConfig->SpdWriteDisable = TRUE;
+ SmbusPreMemConfig->SmbusIoBase = PcdGet16 (PcdSmbusBaseAddress);
+ ASSERT (sizeof (mSmbusRsvdAddresses) <= PCH_MAX_SMBUS_RESERVED_ADDRESS);
+ SmbusPreMemConfig->NumRsvdSmbusAddresses = sizeof (mSmbusRsvdAddresses);
+ CopyMem (
+ SmbusPreMemConfig->RsvdSmbusAddressTable,
+ mSmbusRsvdAddresses,
+ sizeof (mSmbusRsvdAddresses)
+ );
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadLpcPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig;
+ LpcPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Name = %g\n", &LpcPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LpcPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ LPC Configuration
+ ********************************/
+ LpcPreMemConfig->EnhancePort8xhDecoding = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHsioPciePreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
+ HsioPciePreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Name = %g\n", &HsioPciePreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HsioPciePreMemConfig->Header.GuidHob.Header.HobLength));
+
+ HsioPciePreMemConfig->PciePllSsc = 0xFF;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHsioSataPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
+ HsioSataPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Name = %g\n", &HsioSataPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HsioSataPreMemConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHsioPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HSIO_PREMEM_CONFIG *HsioPreMemConfig;
+ HsioPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HsioPreMemConfig->Header.GuidHob.Name = %g\n", &HsioPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HsioPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HsioPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ HsioPreMemConfig->ChipsetInitMessage = TRUE;
+ HsioPreMemConfig->BypassPhySyncReset = FALSE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPcieRpPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig;
+ UINT32 RpIndex;
+
+ PcieRpPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name = %g\n", &PcieRpPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PcieRpPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ for (RpIndex = 0; RpIndex < GetPchMaxPciePortNum (); RpIndex ++) {
+ PcieRpPreMemConfig->RpEnabledMask |= (UINT32) (1 << RpIndex);
+ }
+}
+
+
+static COMPONENT_BLOCK_ENTRY mPchIpBlocksPreMem [] = {
+ {&gPchGeneralPreMemConfigGuid, sizeof (PCH_GENERAL_PREMEM_CONFIG), PCH_GENERAL_PREMEM_CONFIG_REVISION, LoadPchGeneralPreMemConfigDefault},
+ {&gDciPreMemConfigGuid, sizeof (PCH_DCI_PREMEM_CONFIG), DCI_PREMEM_CONFIG_REVISION, LoadDciPreMemConfigDefault},
+ {&gWatchDogPreMemConfigGuid, sizeof (PCH_WDT_PREMEM_CONFIG), WATCH_DOG_PREMEM_CONFIG_REVISION, LoadWatchDogPreMemConfigDefault},
+ {&gTraceHubPreMemConfigGuid, sizeof (PCH_TRACE_HUB_PREMEM_CONFIG), TRACEHUB_PREMEM_CONFIG_REVISION, LoadTraceHubPreMemConfigDefault},
+ {&gHpetPreMemConfigGuid, sizeof (PCH_HPET_PREMEM_CONFIG), HPET_PREMEM_CONFIG_REVISION, LoadHpetPreMemConfigDefault},
+ {&gSmbusPreMemConfigGuid, sizeof (PCH_SMBUS_PREMEM_CONFIG), SMBUS_PREMEM_CONFIG_REVISION, LoadSmbusPreMemConfigDefault},
+ {&gLpcPreMemConfigGuid, sizeof (PCH_LPC_PREMEM_CONFIG), LPC_PREMEM_CONFIG_REVISION, LoadLpcPreMemConfigDefault},
+ {&gHsioPciePreMemConfigGuid, sizeof (PCH_HSIO_PCIE_PREMEM_CONFIG), HSIO_PCIE_PREMEM_CONFIG_REVISION, LoadHsioPciePreMemConfigDefault},
+ {&gHsioSataPreMemConfigGuid, sizeof (PCH_HSIO_SATA_PREMEM_CONFIG), HSIO_SATA_PREMEM_CONFIG_REVISION, LoadHsioSataPreMemConfigDefault},
+ {&gHsioPreMemConfigGuid, sizeof (PCH_HSIO_PREMEM_CONFIG), HSIO_PREMEM_CONFIG_REVISION, LoadHsioPreMemConfigDefault},
+ {&gPcieRpPreMemConfigGuid, sizeof (PCH_PCIE_RP_PREMEM_CONFIG), PCIE_RP_PREMEM_CONFIG_REVISION, LoadPcieRpPreMemConfigDefault},
+
+};
+
+/**
+ Get PCH PREMEM config block table total size.
+
+ @retval Size of PCH PREMEM config block table
+**/
+UINT16
+EFIAPI
+PchGetPreMemConfigBlockTotalSize (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mPchIpBlocksPreMem[0], sizeof (mPchIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ PchAddPreMemConfigBlocks add all PCH PREMEM config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add PCH PREMEM config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+PchAddPreMemConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "PCH AddPreMemConfigBlocks\n"));
+
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchIpBlocksPreMem[0], sizeof (mPchIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
new file mode 100644
index 0000000000..79f3f779dc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
@@ -0,0 +1,194 @@
+/** @file
+ PCH RESET PEIM DRIVER.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PiPei.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <PchAccess.h>
+#include <Ppi/Reset2.h>
+#include <Ppi/PchReset.h>
+#include <Library/ResetSystemLib.h>
+#include <PchResetPlatformSpecific.h>
+
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ );
+
+
+/**
+ Resets the entire platform.
+
+ @param[in] ResetType UEFI defined reset type.
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ switch (ResetType) {
+ case EfiResetWarm:
+ ResetWarm ();
+ break;
+
+ case EfiResetCold:
+ ResetCold ();
+ break;
+
+ case EfiResetShutdown:
+ ResetShutdown ();
+ return;
+
+ case EfiResetPlatformSpecific:
+ ResetPlatformSpecific (ResetStatus, DataSize, ResetData);
+ return;
+
+ default:
+ return;
+ }
+
+ //
+ // Given we should have reset getting here would be bad
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Execute Pch Reset from the host controller.
+
+ @param[in] This Pointer to the PCH_RESET_PPI instance.
+ @param[in] PchResetType Pch Reset Types which includes PchColdReset, PchWarmReset,
+ PchShutdownReset, PchGlobalReset
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER If ResetType is invalid.
+**/
+EFI_STATUS
+EFIAPI
+Reset (
+ IN PCH_RESET_PPI *This,
+ IN PCH_RESET_TYPE PchResetType
+ )
+{
+ PCH_RESET_DATA ResetData;
+
+ switch (PchResetType) {
+ case PchColdReset:
+ ResetCold();
+ break;
+
+ case PchWarmReset:
+ ResetWarm();
+ break;
+
+ case PchShutdownReset:
+ ResetShutdown();
+ break;
+
+ case PchGlobalReset:
+ CopyMem (&ResetData.Guid, &gPchGlobalResetGuid, sizeof (EFI_GUID));
+ StrCpyS (ResetData.Description, PCH_RESET_DATA_STRING_MAX_LENGTH, PCH_PLATFORM_SPECIFIC_RESET_STRING);
+ ResetPlatformSpecific (EFI_SUCCESS, sizeof (PCH_RESET_DATA), &ResetData);
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize PCH Reset APIs
+
+ @retval EFI_SUCCESS APIs are installed successfully
+ @retval EFI_OUT_OF_RESOURCES Can't allocate pool
+**/
+EFI_STATUS
+EFIAPI
+PchInitializeReset (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PCH_RESET_PPI *PeiPchResetPpi;
+ EFI_PEI_PPI_DESCRIPTOR *PeiPchResetDescriptor;
+ EFI_PEI_RESET2_PPI *EfiPeiReset2Ppi;
+ EFI_PEI_PPI_DESCRIPTOR *EfiPeiReset2Descriptor;
+
+ DEBUG ((DEBUG_INFO, "PchInitializeReset() Start\n"));
+
+ PeiPchResetDescriptor = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ PeiPchResetPpi = (PCH_RESET_PPI *) AllocateZeroPool (sizeof (PCH_RESET_PPI));
+ if ((PeiPchResetDescriptor == NULL) ||
+ (PeiPchResetPpi == NULL)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ///
+ /// Initialize the Reset ppi instance
+ ///
+ PeiPchResetPpi->Reset = Reset;
+ PeiPchResetDescriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ PeiPchResetDescriptor->Guid = &gPchResetPpiGuid;
+ PeiPchResetDescriptor->Ppi = PeiPchResetPpi;
+
+ ///
+ /// Install the PCH RESET PPI
+ ///
+ Status = PeiServicesInstallPpi (PeiPchResetDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ EfiPeiReset2Descriptor = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ EfiPeiReset2Ppi = (EFI_PEI_RESET2_PPI *) AllocateZeroPool (sizeof (EFI_PEI_RESET2_PPI));
+ if ((EfiPeiReset2Descriptor == NULL) ||
+ (EfiPeiReset2Ppi == NULL)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ///
+ /// Initialize the EFI Reset2 ppi instance
+ ///
+ EfiPeiReset2Ppi->ResetSystem = ResetSystem;
+
+ EfiPeiReset2Descriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ EfiPeiReset2Descriptor->Guid = &gEfiPeiReset2PpiGuid;
+ EfiPeiReset2Descriptor->Ppi = EfiPeiReset2Ppi;
+
+ Status = PeiServicesInstallPpi (EfiPeiReset2Descriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "PchInitializeReset() End\n"));
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf
new file mode 100644
index 0000000000..b03a986313
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Component description file for PCH Reset Lib Pei Phase
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiPchResetLib
+FILE_GUID = DB91FFF0-5B99-4A88-9EC8-183A2106DCA2
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PchResetLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+DebugLib
+PeiServicesLib
+PeiServicesTablePointerLib
+ResetSystemLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchReset.c
+
+[Ppis]
+gPchResetPpiGuid ## PRODUCES
+gEfiPeiReset2PpiGuid ## PRODUCES
+gPchResetCallbackPpiGuid ## CONSUMES
+
+[Guids]
+gPchGlobalResetGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c
new file mode 100644
index 0000000000..6a017a40a7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c
@@ -0,0 +1,286 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <PchAccess.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchResetLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Ppi/PchReset.h>
+#ifdef FSP_FLAG
+#include <Library/FspCommonLib.h>
+#endif
+/**
+ Dump reset message for debug build readability
+**/
+VOID
+DumpResetMessage (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+ //
+ // ******************************
+ // ** SYSTEM REBOOT !!! **
+ // ******************************
+ //
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n"));
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes PowerCycle, GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+**/
+EFI_STATUS
+PchResetCallback (
+ IN PCH_RESET_TYPE ResetType
+ )
+{
+ EFI_STATUS Status;
+ UINTN Instance;
+ PCH_RESET_CALLBACK_PPI *PchResetCallbackPpi;
+
+ Instance = 0;
+ do {
+ Status = PeiServicesLocatePpi (
+ &gPchResetCallbackPpiGuid,
+ Instance,
+ NULL,
+ (VOID **) &PchResetCallbackPpi
+ );
+
+ switch (Status) {
+ case EFI_SUCCESS:
+ PchResetCallbackPpi->ResetCallback (ResetType);
+ break;
+ case EFI_NOT_FOUND:
+ break;
+ default:
+ ASSERT_EFI_ERROR (Status);
+ break;
+ }
+ ++Instance;
+ } while (Status == EFI_SUCCESS);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetCold);
+#ifdef FSP_FLAG
+ FspApiReturnStatusReset (FSP_STATUS_RESET_REQUIRED_COLD);
+#endif
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetWarm);
+#ifdef FSP_FLAG
+ FspApiReturnStatusReset (FSP_STATUS_RESET_REQUIRED_WARM);
+#endif
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT32 Data32;
+
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetShutdown);
+
+ PchAcpiBaseGet (&ABase);
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (ABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ DumpResetMessage ();
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Internal function to execute the required HECI command for GlobalReset,
+ if failed will use PCH Reest.
+
+**/
+STATIC
+VOID
+PeiPchGlobalReset (
+ VOID
+ )
+{
+ UINTN PchPmcBase;
+
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback (PchGlobalReset);
+
+#ifdef FSP_FLAG
+ FspApiReturnStatusReset (FSP_STATUS_RESET_REQUIRED_3);
+#endif
+
+ PchPmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ //
+ // PCH BIOS Spec Section 4.6 GPIO Reset Requirement
+ //
+ MmioOr32 (PchPmcBase + R_PCH_PMC_ETR3, (UINT32) B_PCH_PMC_ETR3_CF9GR);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ EFI_GUID *GuidPtr;
+
+ if (ResetData == NULL) {
+ DEBUG ((DEBUG_ERROR, "[PeiResetSystemLib] ResetData is not available.\n"));
+ return;
+ }
+ GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
+ if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
+ PeiPchGlobalReset();
+ } else {
+ return;
+ }
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf
new file mode 100644
index 0000000000..a259bdf6ec
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf
@@ -0,0 +1,54 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+DebugLib
+BaseMemoryLib
+PeiServicesLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiResetSystemLib.c
+
+
+[Ppis]
+gPchResetCallbackPpiGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf
new file mode 100644
index 0000000000..9abb7c2107
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+PciLib
+BaseLib
+DebugLib
+BaseMemoryLib
+PeiServicesLib
+MmPciLib
+PchCycleDecodingLib
+FspCommonLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+
+[Sources]
+PeiResetSystemLib.c
+
+
+[Ppis]
+gPchResetCallbackPpiGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
new file mode 100644
index 0000000000..c7b3e864eb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
@@ -0,0 +1,59 @@
+### @file
+# SMM Library instance of Spi Flash Common Library Class
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = SmmSpiFlashCommonLib
+ FILE_GUID = 9632D96E-E849-4217-9217-DC500B8AAE47
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_SMM_DRIVER
+ LIBRARY_CLASS = SpiFlashCommonLib|DXE_SMM_DRIVER
+ CONSTRUCTOR = SmmSpiFlashCommonLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ PciLib
+ IoLib
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ SmmServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ MmPciLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdFlashAreaBaseAddress ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdFlashAreaSize ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdBiosGuardEnable ## CONSUMES
+
+[Sources]
+ SpiFlashCommonSmmLib.c
+ SpiFlashCommon.c
+
+[Protocols]
+ gPchSmmSpiProtocolGuid ## CONSUMES
+ gSmmBiosGuardProtocolGuid ## CONSUMES
+
+[Depex.X64.DXE_SMM_DRIVER]
+ gPchSmmSpiProtocolGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
new file mode 100644
index 0000000000..d95f51af41
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
@@ -0,0 +1,202 @@
+/** @file
+ Wrap EFI_SPI_PROTOCOL to provide some library level interfaces
+ for module use.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/SpiFlashCommonLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <PchAccess.h>
+#include <Library/MmPciLib.h>
+#include <Protocol/Spi.h>
+
+
+PCH_SPI_PROTOCOL *mSpiProtocol;
+
+//
+// FlashAreaBaseAddress and Size for boottime and runtime usage.
+//
+UINTN mFlashAreaBaseAddress = 0;
+UINTN mFlashAreaSize = 0;
+
+/**
+ Enable block protection on the Serial Flash device.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashLock (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Read NumBytes bytes of data from the address specified by
+ PAddress into Buffer.
+
+ @param[in] Address The starting physical address of the read.
+ @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
+ of bytes actually read.
+ @param[out] Buffer The destination data buffer for the read.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ OUT UINT8 *Buffer
+ )
+{
+ ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // This function is implemented specifically for those platforms
+ // at which the SPI device is memory mapped for read. So this
+ // function just do a memory copy for Spi Flash Read.
+ //
+ CopyMem (Buffer, (VOID *) Address, *NumBytes);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write NumBytes bytes of data from Buffer to the address specified by
+ PAddresss.
+
+ @param[in] Address The starting physical address of the write.
+ @param[in,out] NumBytes On input, the number of bytes to write. On output,
+ the actual number of bytes written.
+ @param[in] Buffer The source data buffer for the write.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINT32 Length;
+ UINT32 RemainingBytes;
+
+ ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (Address >= mFlashAreaBaseAddress);
+
+ Offset = Address - mFlashAreaBaseAddress;
+
+ ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+ Status = EFI_SUCCESS;
+ RemainingBytes = *NumBytes;
+
+
+ while (RemainingBytes > 0) {
+ if (RemainingBytes > SECTOR_SIZE_4KB) {
+ Length = SECTOR_SIZE_4KB;
+ } else {
+ Length = RemainingBytes;
+ }
+ Status = mSpiProtocol->FlashWrite (
+ mSpiProtocol,
+ FlashRegionBios,
+ (UINT32) Offset,
+ Length,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ RemainingBytes -= Length;
+ Offset += Length;
+ Buffer += Length;
+ }
+
+ //
+ // Actual number of bytes written
+ //
+ *NumBytes -= RemainingBytes;
+
+ return Status;
+}
+
+/**
+ Erase the block starting at Address.
+
+ @param[in] Address The starting physical address of the block to be erased.
+ This library assume that caller garantee that the PAddress
+ is at the starting address of this block.
+ @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
+ On output, the actual number of bytes erased.
+
+ @retval EFI_SUCCESS. Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+ IN UINTN Address,
+ IN UINTN *NumBytes
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINTN RemainingBytes;
+
+ ASSERT (NumBytes != NULL);
+ if (NumBytes == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (Address >= mFlashAreaBaseAddress);
+
+ Offset = Address - mFlashAreaBaseAddress;
+
+ ASSERT ((*NumBytes % SECTOR_SIZE_4KB) == 0);
+ ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+ Status = EFI_SUCCESS;
+ RemainingBytes = *NumBytes;
+
+
+ Status = mSpiProtocol->FlashErase (
+ mSpiProtocol,
+ FlashRegionBios,
+ (UINT32) Offset,
+ (UINT32) RemainingBytes
+ );
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
new file mode 100644
index 0000000000..8d2238dbf1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
@@ -0,0 +1,60 @@
+/** @file
+ SMM Library instance of SPI Flash Common Library Class
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/SpiFlashCommonLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Protocol/Spi.h>
+
+extern PCH_SPI_PROTOCOL *mSpiProtocol;
+
+extern UINTN mFlashAreaBaseAddress;
+extern UINTN mFlashAreaSize;
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library
+ instance.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+ @retval EFI_ERROR Please reference LocateProtocol for error code details.
+**/
+EFI_STATUS
+EFIAPI
+SmmSpiFlashCommonLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mFlashAreaBaseAddress = (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+ mFlashAreaSize = (UINTN)PcdGet32 (PcdFlashAreaSize);
+
+ //
+ // Locate the SMM SPI protocol.
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gPchSmmSpiProtocolGuid,
+ NULL,
+ (VOID **) &mSpiProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
new file mode 100644
index 0000000000..128f7adcea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BasePchSpiCommonLib
+ FILE_GUID = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchSpiCommonLib
+
+[Sources]
+ SpiCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..46184d4994
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1058 @@
+/** @file
+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/MmPciLib.h>
+#include <Protocol/Spi.h>
+#include <Library/PchSpiCommonLib.h>
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINTN PchSpiBar0;
+ UINT32 Data32;
+
+ //
+ // Initialize the SPI protocol instance
+ //
+ SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+ SpiInstance->Handle = NULL;
+ SpiInstance->SpiProtocol.Revision = PCH_SPI_SERVICES_REVISION;
+ SpiInstance->SpiProtocol.FlashRead = SpiProtocolFlashRead;
+ SpiInstance->SpiProtocol.FlashWrite = SpiProtocolFlashWrite;
+ SpiInstance->SpiProtocol.FlashErase = SpiProtocolFlashErase;
+ SpiInstance->SpiProtocol.FlashReadSfdp = SpiProtocolFlashReadSfdp;
+ SpiInstance->SpiProtocol.FlashReadJedecId = SpiProtocolFlashReadJedecId;
+ SpiInstance->SpiProtocol.FlashWriteStatus = SpiProtocolFlashWriteStatus;
+ SpiInstance->SpiProtocol.FlashReadStatus = SpiProtocolFlashReadStatus;
+ SpiInstance->SpiProtocol.GetRegionAddress = SpiProtocolGetRegionAddress;
+ SpiInstance->SpiProtocol.ReadPchSoftStrap = SpiProtocolReadPchSoftStrap;
+ SpiInstance->SpiProtocol.ReadCpuSoftStrap = SpiProtocolReadCpuSoftStrap;
+
+ SpiInstance->PchSpiBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+
+ PchAcpiBaseGet (&(SpiInstance->PchAcpiBase));
+ ASSERT (SpiInstance->PchAcpiBase != 0);
+
+ PchSpiBar0 = MmioRead32 (SpiInstance->PchSpiBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+ if (PchSpiBar0 == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n"));
+ ASSERT (FALSE);
+ }
+
+ if ((MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC) & B_PCH_SPI_HSFSC_FDV) == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use the Hardware Sequencing registers!\n"));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Get Region 0 - 7 read Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->ReadPermission = MmioRead8 (PchSpiBar0 + R_PCH_SPI_FRAP) & B_PCH_SPI_FRAP_BRRA_MASK;
+ DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", SpiInstance->ReadPermission));
+ //
+ // Get Region 0 - 7 write Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->WritePermission = (UINT8) ((MmioRead16 (PchSpiBar0 + R_PCH_SPI_FRAP) &
+ B_PCH_SPI_FRAP_BRWA_MASK) >> N_PCH_SPI_FRAP_BRWA);
+ DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", SpiInstance->WritePermission));
+
+ SpiInstance->SfdpVscc0Value = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0);
+ DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc0Value));
+ SpiInstance->SfdpVscc1Value = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP1_VSCC1);
+ DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc1Value));
+
+ //
+ // Select to Flash Map 0 Register to get the number of flash Component
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP0)
+ );
+
+ //
+ // Copy Zero based Number Of Components
+ //
+ SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0 + R_PCH_SPI_FDOD) & B_PCH_SPI_FDBAR_NC) >> N_PCH_SPI_FDBAR_NC);
+ DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance->NumberOfComponents + 1));
+
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_COMP | R_PCH_SPI_FCBA_FLCOMP)
+ );
+
+ //
+ // Copy Component 0 Density
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ if (SpiInstance->NumberOfComponents > 0) {
+ SpiInstance->Component1StartAddr = V_PCH_SPI_FLCOMP_COMP_512KB <<
+ (Data32 & B_PCH_SPI_FLCOMP_COMP0_MASK);
+ DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Component1StartAddr));
+ SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
+ (V_PCH_SPI_FLCOMP_COMP_512KB <<
+ ((Data32 & B_PCH_SPI_FLCOMP_COMP1_MASK) >>
+ N_PCH_SPI_FLCOMP_COMP1));
+ } else {
+ SpiInstance->TotalFlashSize = V_PCH_SPI_FLCOMP_COMP_512KB <<
+ (Data32 & B_PCH_SPI_FLCOMP_COMP0_MASK);
+ }
+ DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashSize));
+
+ //
+ // Select FLASH_MAP1 to get Flash PCH Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_PCH_SPI_FDOC),
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP1)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ SpiInstance->PchStrapBaseAddr = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_FPSBA)
+ >> N_PCH_SPI_FDBAR_FPSBA)
+ << N_PCH_SPI_FDBAR_FPSBA_REPR);
+ DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance->PchStrapBaseAddr));
+ ASSERT (SpiInstance->PchStrapBaseAddr != 0);
+ //
+ // PCH Strap Length, [31:24] represents number of Dwords
+ //
+ SpiInstance->PchStrapSize = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_PCHSL)
+ >> N_PCH_SPI_FDBAR_PCHSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance->PchStrapSize));
+
+ //
+ // Select FLASH_MAP2 to get Flash CPU Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_PCH_SPI_FDOC),
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP2)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ SpiInstance->CpuStrapBaseAddr = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_FCPUSBA)
+ >> N_PCH_SPI_FDBAR_FCPUSBA)
+ << N_PCH_SPI_FDBAR_FCPUSBA_REPR);
+ DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBaseAddr));
+ ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
+ //
+ // CPU Strap Length, [15:8] represents number of Dwords
+ //
+ SpiInstance->CpuStrapSize = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_CPUSL)
+ >> N_PCH_SPI_FDBAR_CPUSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance->CpuStrapSize));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delay for at least the request number of microseconds for Runtime usage.
+
+ @param[in] ABase Acpi base address
+ @param[in] Microseconds Number of microseconds to delay.
+
+**/
+VOID
+EFIAPI
+PchPmTimerStallRuntimeSafe (
+ IN UINT16 ABase,
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINTN CurrentTick;
+ UINTN OriginalTick;
+ UINTN RemainingTick;
+
+ if (Microseconds == 0) {
+ return;
+ }
+
+ OriginalTick = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+ CurrentTick = OriginalTick;
+
+ //
+ // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks
+ //
+ Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
+
+ //
+ // The loops needed by timer overflow
+ //
+ Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+ //
+ // Remaining clocks within one loop
+ //
+ RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+ //
+ // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra
+ // one I/O operation, and maybe generate SMI
+ //
+ while ((Counts != 0) || (RemainingTick > CurrentTick)) {
+ CurrentTick = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+ //
+ // Check if timer overflow
+ //
+ if ((CurrentTick < OriginalTick)) {
+ if (Counts != 0) {
+ Counts--;
+ } else {
+ //
+ // If timer overflow and Counts equ to 0, that means we already stalled more than
+ // RemainingTick, break the loop here
+ //
+ break;
+ }
+ }
+
+ OriginalTick = CurrentTick;
+ }
+}
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleRead,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleWrite,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleErase,
+ Address,
+ ByteCount,
+ NULL
+ );
+ return Status;
+}
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 FlashAddress;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FlashAddress = 0;
+ if (ComponentNumber == FlashComponent1) {
+ FlashAddress = SpiInstance->Component1StartAddr;
+ }
+ FlashAddress += Address;
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadSfdp,
+ FlashAddress,
+ ByteCount,
+ SfdpData
+ );
+ return Status;
+}
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 Address;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = 0;
+ if (ComponentNumber == FlashComponent1) {
+ Address = SpiInstance->Component1StartAddr;
+ }
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadJedecId,
+ Address,
+ ByteCount,
+ JedecId
+ );
+ return Status;
+}
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleWriteStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchSpiBar0;
+ UINT32 ReadValue;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (FlashRegionType >= FlashRegionMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FlashRegionType == FlashRegionAll) {
+ *BaseAddress = 0;
+ *RegionSize = SpiInstance->TotalFlashSize;
+ return EFI_SUCCESS;
+ }
+
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ ReadValue = MmioRead32 (PchSpiBar0 + (R_PCH_SPI_FREG0_FLASHD + (S_PCH_SPI_FREGX * ((UINT32) FlashRegionType))));
+ ReleaseSpiBar0 (SpiInstance);
+
+ //
+ // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h
+ //
+ if (ReadValue == B_PCH_SPI_FREGX_BASE_MASK) {
+ return EFI_DEVICE_ERROR;
+ }
+ *BaseAddress = ((ReadValue & B_PCH_SPI_FREGX_BASE_MASK) >> N_PCH_SPI_FREGX_BASE) <<
+ N_PCH_SPI_FREGX_BASE_REPR;
+ //
+ // Region limit address Bits[11:0] are assumed to be FFFh
+ //
+ *RegionSize = ((((ReadValue & B_PCH_SPI_FREGX_LIMIT_MASK) >> N_PCH_SPI_FREGX_LIMIT) + 1) <<
+ N_PCH_SPI_FREGX_LIMIT_REPR) - *BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->PchStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // PCH Strap Flash Address = FPSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->PchStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read PCH Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->CpuStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // CPU Strap Flash Address = FCPUSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->CpuStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read Cpu Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor
+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN FLASH_CYCLE_TYPE FlashCycleType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ SPI_INSTANCE *SpiInstance;
+ UINTN SpiBaseAddress;
+ UINTN PchSpiBar0;
+ UINT32 HardwareSpiAddr;
+ UINT32 FlashRegionSize;
+ UINT32 SpiDataCount;
+ UINT32 FlashCycle;
+ UINT8 BiosCtlSave;
+ UINT32 SmiEnSave;
+ UINT16 ABase;
+
+ Status = EFI_SUCCESS;
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ ABase = SpiInstance->PchAcpiBase;
+
+ //
+ // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
+ // whose SMI handler accesses flash (e.g. for error logging)
+ //
+ // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]='1'),
+ // clearing B_GBL_SMI_EN will not have effect. In this situation, some other
+ // synchronization methods must be applied here or in the consumer of the
+ // SendSpiCmd. An example method is disabling the specific SMI sources
+ // whose SMI handlers access flash before flash cycle and re-enabling the SMI
+ // sources after the flash cycle .
+ //
+ SmiEnSave = IoRead32 ((UINTN) (ABase + R_PCH_SMI_EN));
+ IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI));
+ BiosCtlSave = MmioRead8 (SpiBaseAddress + R_PCH_SPI_BC) & B_PCH_SPI_BC_SRC;
+
+ //
+ // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ Status = DisableBiosWriteProtect ();
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ MmioAndThenOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) (~B_PCH_SPI_BC_SRC),
+ (UINT8) (V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_DIS << N_PCH_SPI_BC_SRC)
+ );
+ }
+ //
+ // Make sure it's safe to program the command.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) {
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+
+ Status = SpiProtocolGetRegionAddress (This, FlashRegionType, &HardwareSpiAddr, &FlashRegionSize);
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ HardwareSpiAddr += Address;
+ if ((Address + ByteCount) > FlashRegionSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+
+ //
+ // Check for PCH SPI hardware sequencing required commands
+ //
+ FlashCycle = 0;
+ switch (FlashCycleType) {
+ case FlashCycleRead:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleWrite:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleErase:
+ if (((ByteCount % SIZE_4KB) != 0) ||
+ ((HardwareSpiAddr % SIZE_4KB) != 0)) {
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+ break;
+ case FlashCycleReadSfdp:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_SFDP << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadJedecId:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_JEDEC_ID << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleWriteStatus:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadStatus:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ default:
+ //
+ // Unrecognized Operation
+ //
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ break;
+ }
+
+ do {
+ SpiDataCount = ByteCount;
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleReadSfdp)) {
+ //
+ // Trim at 256 byte boundary per operation,
+ // - PCH SPI controller requires trimming at 4KB boundary
+ // - Some SPI chips require trimming at 256 byte boundary for write operation
+ // - Trimming has limited performance impact as we can read / write atmost 64 byte
+ // per operation
+ //
+ if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+ SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+ }
+ //
+ // Calculate the number of bytes to shift in/out during the SPI data cycle.
+ // Valid settings for the number of bytes duing each data portion of the
+ // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ if (SpiDataCount >= 64) {
+ SpiDataCount = 64;
+ } else if ((SpiDataCount &~0x07) != 0) {
+ SpiDataCount = SpiDataCount &~0x07;
+ }
+ }
+ if (FlashCycleType == FlashCycleErase) {
+ if (((ByteCount / SIZE_64KB) != 0) &&
+ ((ByteCount % SIZE_64KB) == 0) &&
+ ((HardwareSpiAddr % SIZE_64KB) == 0)) {
+ if (HardwareSpiAddr < SpiInstance->Component1StartAddr) {
+ //
+ // Check whether Component0 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc0Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ } else {
+ //
+ // Check whether Component1 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc1Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ }
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ if (SpiDataCount == SIZE_4KB) {
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_4K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+ } else {
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_64K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+ }
+ }
+ //
+ // If it's write cycle, load data into the SPI data buffer.
+ //
+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ MmioWrite8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, Buffer[Index]);
+ }
+ } else {
+ //
+ // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, *(UINT32 *) (Buffer + Index));
+ }
+ }
+ }
+
+ //
+ // Set the Flash Address
+ //
+ MmioWrite32 (
+ (PchSpiBar0 + R_PCH_SPI_FADDR),
+ (UINT32) (HardwareSpiAddr & B_PCH_SPI_FADDR_MASK)
+ );
+
+ //
+ // Set Data count, Flash cycle, and Set Go bit to start a cycle
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_HSFSC,
+ (UINT32) (~(B_PCH_SPI_HSFSC_FDBC_MASK | B_PCH_SPI_HSFSC_CYCLE_MASK)),
+ (UINT32) ((((SpiDataCount - 1) << N_PCH_SPI_HSFSC_FDBC) & B_PCH_SPI_HSFSC_FDBC_MASK) | FlashCycle | B_PCH_SPI_HSFSC_CYCLE_FGO)
+ );
+ //
+ // end of command execution
+ //
+ // Wait the SPI cycle to complete.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) {
+ ASSERT (FALSE);
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+ //
+ // If it's read cycle, load data into the call's buffer.
+ //
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleReadSfdp) ||
+ (FlashCycleType == FlashCycleReadJedecId) ||
+ (FlashCycleType == FlashCycleReadStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ Buffer[Index] = MmioRead8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+ }
+ } else {
+ //
+ // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ *(UINT32 *) (Buffer + Index) = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+ }
+ }
+ }
+
+ HardwareSpiAddr += SpiDataCount;
+ Buffer += SpiDataCount;
+ ByteCount -= SpiDataCount;
+ } while (ByteCount > 0);
+
+SendSpiCmdEnd:
+ //
+ // Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ EnableBiosWriteProtect ();
+ MmioAndThenOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) ~B_PCH_SPI_BC_SRC,
+ BiosCtlSave
+ );
+ }
+ //
+ // Restore SMIs.
+ //
+ IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave);
+
+ ReleaseSpiBar0 (SpiInstance);
+
+ return Status;
+}
+
+/**
+ Wait execution cycle to complete on the SPI interface.
+
+ @param[in] This The SPI protocol instance
+ @param[in] PchSpiBar0 Spi MMIO base address
+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN ErrorCheck
+ )
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ UINT32 Data32;
+ SPI_INSTANCE *SpiInstance;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ //
+ // Convert the wait period allowed into to tick count
+ //
+ WaitCount = WAIT_TIME / WAIT_PERIOD;
+ //
+ // Wait for the SPI cycle to complete.
+ //
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC);
+ if ((Data32 & B_PCH_SPI_HSFSC_SCIP) == 0) {
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_HSFSC, B_PCH_SPI_HSFSC_FCERR | B_PCH_SPI_HSFSC_FDONE);
+ if (((Data32 & B_PCH_SPI_HSFSC_FCERR) != 0) && (ErrorCheck == TRUE)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+ PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, WAIT_PERIOD);
+ }
+ return FALSE;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf
new file mode 100644
index 0000000000..52d7c8bbaf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Component information file for PCH HD Audio Library
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxePchHdaLib
+FILE_GUID = DA915B7F-EE08-4C1D-B3D0-DE7C52AB155A
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchHdaLib
+
+
+[LibraryClasses]
+BaseLib
+DebugLib
+MemoryAllocationLib
+BaseMemoryLib
+PchInfoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+
+
+[Sources]
+PchHdaLib.c
+PchHdaEndpoints.c
+PchHdaNhltConfig.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c
new file mode 100644
index 0000000000..11c6ec0269
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c
@@ -0,0 +1,318 @@
+/** @file
+ This file contains HD Audio NHLT Endpoints definitions
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PchHdaEndpoints.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch1_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 48000,
+ 96000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 192000,
+ 4,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz24bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {24},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz32bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {32},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch4_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 4,
+ 48000,
+ 384000,
+ 8,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_QUAD,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch4_48kHz32bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 4,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {32},
+ KSAUDIO_SPEAKER_QUAD,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE NarrowbandFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 8000,
+ 16000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE WidebandFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 16000,
+ 32000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE A2dpFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {24},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX1 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX2 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX4 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointBtRender = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae30, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceBt, // DeviceType
+ 0, // Direction
+ 2, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointBtCapture = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae30, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceBt, // DeviceType
+ 1, // Direction
+ 2, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointI2sRender = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 1, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae34, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceI2s, // DeviceType
+ 0, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointI2sCapture = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 1, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae34, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceI2s, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX1Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x00, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX1ConfigSize = sizeof (DmicX1Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX2Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x01, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+ 0x0A // ArrayType
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX2ConfigSize = sizeof (DmicX2Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX4Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x01, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+ 0x0D // ArrayType
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX4ConfigSize = sizeof (DmicX4Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 BtConfig[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BtConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sRender1Config[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRender1ConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sRender2Config[] = {0x01};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRender2ConfigSize = sizeof (I2sRender2Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sCaptureConfig[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sCaptureConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfiguration[] = { 0xEFBEADDE };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfigurationSize = sizeof (NhltConfiguration);
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c
new file mode 100644
index 0000000000..e577cd9038
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c
@@ -0,0 +1,842 @@
+/** @file
+ PCH HD Audio Library implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PchHdaLib.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Returns pointer to Endpoint ENDPOINT_DESCRIPTOR structure.
+
+ @param[in] *NhltTable Endpoint for which Format address is retrieved
+ @param[in] FormatIndex Index of Format to be retrieved
+
+ @retval Pointer to ENDPOINT_DESCRIPTOR structure with given index
+**/
+ENDPOINT_DESCRIPTOR *
+GetNhltEndpoint (
+ IN CONST NHLT_ACPI_TABLE *NhltTable,
+ IN CONST UINT8 EndpointIndex
+ )
+{
+ UINT8 i;
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ Endpoint = (ENDPOINT_DESCRIPTOR*) (NhltTable->EndpointDescriptors);
+
+ if (EndpointIndex > NhltTable->EndpointCount) {
+ return NULL;
+ }
+
+ for (i = 0; i < EndpointIndex; i++) {
+ Endpoint = (ENDPOINT_DESCRIPTOR*) ((UINT8*) (Endpoint) + Endpoint->EndpointDescriptorLength);
+ }
+
+ return Endpoint;
+}
+
+/**
+ Returns pointer to Endpoint Specific Configuration SPECIFIC_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which config address is retrieved
+
+ @retval Pointer to SPECIFIC_CONFIG structure with endpoint's capabilities
+**/
+SPECIFIC_CONFIG *
+GetNhltEndpointDeviceCapabilities (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ return (SPECIFIC_CONFIG*) (&Endpoint->EndpointConfig);
+}
+
+/**
+ Returns pointer to all Formats Configuration FORMATS_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which Formats address is retrieved
+
+ @retval Pointer to FORMATS_CONFIG structure
+**/
+FORMATS_CONFIG *
+GetNhltEndpointFormatsConfig (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ FORMATS_CONFIG *FormatsConfig;
+ FormatsConfig = (FORMATS_CONFIG*) ((UINT8*) (&Endpoint->EndpointConfig)
+ + sizeof (Endpoint->EndpointConfig.CapabilitiesSize)
+ + Endpoint->EndpointConfig.CapabilitiesSize);
+
+ return FormatsConfig;
+}
+
+/**
+ Returns pointer to Format Configuration FORMAT_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which Format address is retrieved
+ @param[in] FormatIndex Index of Format to be retrieved
+
+ @retval Pointer to FORMAT_CONFIG structure with given index
+**/
+FORMAT_CONFIG *
+GetNhltEndpointFormat (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT8 FormatIndex
+ )
+{
+ UINT8 i;
+ UINT32 Length;
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+
+ Length = 0;
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ Format = FormatsConfig->FormatsConfiguration;
+
+ if (FormatIndex > FormatsConfig->FormatsCount) {
+ return NULL;
+ }
+
+ for (i = 0; i < FormatIndex; i++) {
+ Length = sizeof (Format->Format) + Format->FormatConfiguration.CapabilitiesSize
+ + sizeof (Format->FormatConfiguration.CapabilitiesSize);
+ Format = (FORMAT_CONFIG*) ((UINT8*) (Format) + Length);
+ }
+
+ return Format;
+}
+
+/**
+ Returns pointer to OED Configuration SPECIFIC_CONFIG structure.
+
+ @param[in] *NhltTable NHLT table for which OED address is retrieved
+
+ @retval Pointer to SPECIFIC_CONFIG structure with NHLT capabilities
+**/
+SPECIFIC_CONFIG *
+GetNhltOedConfig (
+ IN CONST NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ SPECIFIC_CONFIG *OedConfig;
+
+ Endpoint = GetNhltEndpoint (NhltTable, (NhltTable->EndpointCount));
+ OedConfig = (SPECIFIC_CONFIG*) ((UINT8*) (Endpoint));
+
+ return OedConfig;
+}
+
+/**
+ Prints Format configuration.
+
+ @param[in] *Format Format to be printed
+
+ @retval None
+**/
+VOID
+NhltFormatDump (
+ IN CONST FORMAT_CONFIG *Format
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------------------- FORMAT -------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wFormatTag = 0x%x\n", Format->Format.Format.wFormatTag));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nChannels = %d\n", Format->Format.Format.nChannels));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nSamplesPerSec = %d\n", Format->Format.Format.nSamplesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nAvgBytesPerSec = %d\n", Format->Format.Format.nAvgBytesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nBlockAlign = %d\n", Format->Format.Format.nBlockAlign));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wBitsPerSample = %d\n", Format->Format.Format.wBitsPerSample));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.cbSize = %d\n", Format->Format.Format.cbSize));
+ DEBUG ((DEBUG_INFO, " Format->Format.Samples = %d\n", Format->Format.Samples));
+ DEBUG ((DEBUG_INFO, " Format->Format.dwChannelMask = 0x%x\n", Format->Format.dwChannelMask));
+ DEBUG ((DEBUG_INFO, " Format->Format.SubFormat = %g\n", Format->Format.SubFormat));
+
+
+ DEBUG ((DEBUG_INFO, " Format->FormatConfiguration.CapabilitiesSize = %d B\n", Format->FormatConfiguration.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Format->FormatConfiguration.Capabilities:"));
+ for (i = 0; i < ( Format->FormatConfiguration.CapabilitiesSize ) ; i++) {
+ if (i % 16 == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Format->FormatConfiguration.Capabilities[i]));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints Endpoint configuration.
+
+ @param[in] *Endpoint Endpoint to be printed
+
+ @retval None
+**/
+VOID
+NhltEndpointDump (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ UINT8 i;
+ FORMATS_CONFIG *FormatsConfigs;
+ FORMAT_CONFIG *Format;
+
+ DEBUG ((DEBUG_INFO, "------------------------------ ENDPOINT ------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceDescriptorLength = %d B\n", Endpoint->EndpointDescriptorLength));
+ DEBUG ((DEBUG_INFO, " Endpoint->LinkType = 0x%x\n", Endpoint->LinkType));
+ DEBUG ((DEBUG_INFO, " Endpoint->InstanceId = 0x%x\n", Endpoint->InstanceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwVendorId = 0x%x\n", Endpoint->HwVendorId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwDeviceId = 0x%x\n", Endpoint->HwDeviceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwRevisionId = 0x%x\n", Endpoint->HwRevisionId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwSubsystemId = 0x%x\n", Endpoint->HwSubsystemId));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceType = 0x%x\n", Endpoint->DeviceType));
+ DEBUG ((DEBUG_INFO, " Endpoint->Direction = 0x%x\n", Endpoint->Direction));
+ DEBUG ((DEBUG_INFO, " Endpoint->VirtualBusId = 0x%x\n", Endpoint->VirtualBusId));
+
+ DEBUG ((DEBUG_INFO, " Endpoint->EndpointConfig.CapabilitiesSize = %d B\n", Endpoint->EndpointConfig.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Endpoint->EndpointConfig.Capabilities:"));
+ for (i = 0; i < (Endpoint->EndpointConfig.CapabilitiesSize ) ; i++) {
+ if (i % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Endpoint->EndpointConfig.Capabilities[i]));
+ }
+
+ FormatsConfigs = GetNhltEndpointFormatsConfig (Endpoint);
+
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->FormatsConfig.FormatsCount = %d\n", FormatsConfigs->FormatsCount));
+ for (i = 0; i < FormatsConfigs->FormatsCount; i++) {
+ Format = GetNhltEndpointFormat (Endpoint, i);
+ if (Format != NULL) {
+ NhltFormatDump (Format);
+ }
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints OED (Offload Engine Driver) configuration.
+
+ @param[in] *OedConfig OED to be printed
+
+ @retval None
+**/
+VOID
+NhltOedConfigDump (
+ IN CONST SPECIFIC_CONFIG *OedConfig
+ )
+{
+ UINT8 i;
+
+ DEBUG ((DEBUG_INFO, "-------------------------- OED CONFIGURATION -------------------------\n"));
+ DEBUG ((DEBUG_INFO, " OedConfig->CapabilitiesSize = %d B\n", OedConfig->CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " OedConfig->Capabilities:"));
+ for (i = 0; i < (OedConfig->CapabilitiesSize) ; i++) {
+ if (i % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", OedConfig->Capabilities[i]));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints NHLT (Non HDA-Link Table) to be exposed via ACPI (aka. OED (Offload Engine Driver) Configuration Table).
+
+ @param[in] *NhltTable The NHLT table to print
+
+ @retval None
+**/
+VOID
+NhltAcpiTableDump (
+ IN NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINT8 i;
+
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "--- NHLT ACPI Table Dump [OED (Offload Engine Driver) Configuration] ---\n"));
+
+ DEBUG ((DEBUG_INFO, "sizeof NHLT_ACPI_TABLE = %d B\n", sizeof (NHLT_ACPI_TABLE)));
+ DEBUG ((DEBUG_INFO, "sizeof EFI_ACPI_DESCRIPTION_HEADER = %d B\n", sizeof (EFI_ACPI_DESCRIPTION_HEADER)));
+ DEBUG ((DEBUG_INFO, "sizeof ENDPOINT_DESCRIPTOR = %d B\n", sizeof (ENDPOINT_DESCRIPTOR)));
+ DEBUG ((DEBUG_INFO, "sizeof SPECIFIC_CONFIG = %d B\n", sizeof (SPECIFIC_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof FORMATS_CONFIG = %d B\n", sizeof (FORMATS_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof FORMAT_CONFIG = %d B\n", sizeof (FORMAT_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof WAVEFORMATEXTENSIBLE = %d B\n", sizeof (WAVEFORMATEXTENSIBLE)));
+
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Signature = 0x%08x\n", NhltTable->Header.Signature));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Length = 0x%08x\n", NhltTable->Header.Length));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Revision = 0x%02x\n", NhltTable->Header.Revision));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Checksum = 0x%02x\n", NhltTable->Header.Checksum));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemId = %a\n", NhltTable->Header.OemId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemTableId = 0x%lx\n", NhltTable->Header.OemTableId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemRevision = 0x%08x\n", NhltTable->Header.OemRevision));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.CreatorId = 0x%08x\n", NhltTable->Header.CreatorId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.CreatorRevision = 0x%08x\n", NhltTable->Header.CreatorRevision));
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE EndpointCount = %d\n", NhltTable->EndpointCount));
+ for (i = 0; i < NhltTable->EndpointCount; i++) {
+ NhltEndpointDump (GetNhltEndpoint (NhltTable, i));
+ }
+
+ NhltOedConfigDump (GetNhltOedConfig (NhltTable));
+ DEBUG ((DEBUG_INFO, "----------------------------------------------------------------------\n"));
+
+ DEBUG_CODE_END ();
+}
+
+/**
+ Constructs FORMATS_CONFIGS structure based on given formats list.
+
+ @param[in][out] *Endpoint Endpoint for which format structures are created
+ @param[in] FormatBitmask Bitmask of formats supported for given endpoint
+
+ @retval Size of created FORMATS_CONFIGS structure
+**/
+UINT32
+NhltFormatsConstructor (
+ IN OUT ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT32 FormatsBitmask
+ )
+{
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+ UINT8 FormatIndex;
+ UINT32 FormatsConfigLength;
+
+ DEBUG ((DEBUG_INFO, "NhltFormatsConstructor() Start, FormatsBitmask = 0x%08x\n", FormatsBitmask));
+
+ FormatsConfig = NULL;
+ FormatIndex = 0;
+ FormatsConfigLength = 0;
+
+ if (!FormatsBitmask) {
+ DEBUG ((DEBUG_WARN, "No supported format found!\n"));
+ return 0;
+ }
+
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ FormatsConfig->FormatsCount = 0;
+
+ if (FormatsBitmask & B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicStereo16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo16BitFormatConfig, DmicStereo16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicStereo32BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo32BitFormatConfig, DmicStereo32BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicQuad16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad16BitFormatConfig, DmicQuad16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicQuad32BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad32BitFormatConfig, DmicQuad32BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch1_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicMono16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicMono16BitFormatConfig, DmicMono16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_NARROWBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_NARROWBAND_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_WIDEBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_WIDEBAND_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &WidebandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_A2DP_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_A2DP_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &A2dpFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk298Render4ch48kHz24bitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk298Render4ch48kHz24bitFormatConfig, I2sRtk298Render4ch48kHz24bitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk298Capture4ch48kHz24bitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk298Capture4ch48kHz24bitFormatConfig, I2sRtk298Capture4ch48kHz24bitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk286S2ch48kHzFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk286S2ch48kHzFormatConfig, I2sRtk286S2ch48kHzFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sAdi4ch48kHzFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sAdi4ch48kHzFormatConfig, I2sAdi4ch48kHzFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2s48kHz24bitMasterFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2s48kHz24bitMasterFormatConfig, I2s48kHz24bitMasterFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2s48kHz24bitSlaveFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2s48kHz24bitSlaveFormatConfig, I2s48kHz24bitSlaveFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sPcm8kHz16bitMasterFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sPcm8kHz16bitMasterFormatConfig, I2sPcm8kHz16bitMasterFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sPcm8kHz16bitSlaveFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sPcm8kHz16bitSlaveFormatConfig, I2sPcm8kHz16bitSlaveFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "NhltFormatsConstructor() End, FormatsCount = %d, FormatsConfigLength = %d B\n", FormatsConfig->FormatsCount, FormatsConfigLength));
+ return FormatsConfigLength;
+}
+
+/**
+ Constructs NHLT_ENDPOINT structure based on given endpoint type.
+
+ @param[in][out] *NhltTable NHLT table for which endpoint is created
+ @param[in] EndpointType Type of endpoint to be created
+ @param[in] EndpointFormatsBitmask Bitmask of formats supported by endpoint
+ @param[in] EndpointIndex Endpoint index in NHLT table
+
+ @retval Size of created NHLT_ENDPOINT structure
+**/
+UINT32
+NhltEndpointConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN NHLT_ENDPOINT EndpointType,
+ IN UINT32 EndpointFormatsBitmask,
+ IN UINT8 EndpointIndex
+ )
+{
+
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ SPECIFIC_CONFIG *EndpointConfig;
+ CONST UINT8 *EndpointConfigBuffer;
+ UINT32 EndpointConfigBufferSize;
+ UINT32 EndpointDescriptorLength;
+
+ DEBUG ((DEBUG_INFO, "NhltEndpointConstructor() Start, EndpointIndex = %d\n", EndpointIndex));
+
+ EndpointDescriptorLength = 0;
+ Endpoint = GetNhltEndpoint (NhltTable, EndpointIndex);
+ if (Endpoint == NULL) {
+ return 0;
+ }
+ EndpointDescriptorLength = sizeof (ENDPOINT_DESCRIPTOR)
+ - sizeof (SPECIFIC_CONFIG)
+ - sizeof (FORMAT_CONFIG);
+
+ switch (EndpointType) {
+ case HdaDmicX1:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX1\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX1, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX1Config;
+ EndpointConfigBufferSize = DmicX1ConfigSize;
+ break;
+ case HdaDmicX2:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX2\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX2, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX2Config;
+ EndpointConfigBufferSize = DmicX2ConfigSize;
+ break;
+ case HdaDmicX4:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX4\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX4, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX4Config;
+ EndpointConfigBufferSize = DmicX4ConfigSize;
+ break;
+ case HdaBtRender:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtRender\n"));
+ CopyMem (Endpoint, &HdaEndpointBtRender, sizeof (ENDPOINT_DESCRIPTOR));
+ if (GetPchSeries () == PchH) {
+ Endpoint->VirtualBusId = 0;
+ }
+
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ break;
+ case HdaBtCapture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtCapture\n"));
+ CopyMem (Endpoint, &HdaEndpointBtCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ if (GetPchSeries () == PchH) {
+ Endpoint->VirtualBusId = 0;
+ }
+
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ break;
+ case HdaI2sRender1:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRender1\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sRender, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sRender1Config;
+ EndpointConfigBufferSize = I2sRender1ConfigSize;
+ break;
+ case HdaI2sRender2:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRender2\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sRender, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sRender2Config;
+ EndpointConfigBufferSize = I2sRender2ConfigSize;
+ break;
+ case HdaI2sCapture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sCapture\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sCaptureConfig;
+ EndpointConfigBufferSize = I2sCaptureConfigSize;
+ break;
+ default:
+ DEBUG ((DEBUG_WARN, "Unknown endpoint!\n"));
+ return 0;
+ }
+
+ EndpointConfig = GetNhltEndpointDeviceCapabilities (Endpoint);
+ EndpointConfig->CapabilitiesSize = EndpointConfigBufferSize;
+ CopyMem (EndpointConfig->Capabilities, EndpointConfigBuffer, EndpointConfig->CapabilitiesSize);
+ EndpointDescriptorLength += sizeof (*EndpointConfig)
+ - sizeof (EndpointConfig->Capabilities)
+ + EndpointConfig->CapabilitiesSize;
+
+ EndpointDescriptorLength += NhltFormatsConstructor (Endpoint, EndpointFormatsBitmask);
+ Endpoint->EndpointDescriptorLength = EndpointDescriptorLength;
+
+ DEBUG ((DEBUG_INFO, "NhltEndpointConstructor() End, EndpointDescriptorLength = %d B\n", Endpoint->EndpointDescriptorLength));
+ return Endpoint->EndpointDescriptorLength;
+}
+
+/**
+ Constructs SPECIFIC_CONFIG structure for OED configuration.
+
+ @param[in][out] *NhltTable NHLT table for which OED config is created
+
+ @retval Size of created SPECIFIC_CONFIG structure
+**/
+UINT32
+NhltOedConfigConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ SPECIFIC_CONFIG *OedConfig;
+ UINT32 OedConfigLength;
+
+ OedConfigLength = 0;
+ OedConfig = GetNhltOedConfig (NhltTable);
+
+ OedConfig->CapabilitiesSize = NhltConfigurationSize;
+ CopyMem (OedConfig->Capabilities, (UINT8*) NhltConfiguration, NhltConfigurationSize);
+
+ OedConfigLength = sizeof (*OedConfig)
+ - sizeof (OedConfig->Capabilities)
+ + OedConfig->CapabilitiesSize;
+
+ return OedConfigLength;
+}
+
+/**
+ Constructs NHLT_ACPI_TABLE structure based on given Endpoints list.
+
+ @param[in] *EndpointTable List of endpoints for NHLT
+ @param[in][out] **NhltTable NHLT table to be created
+ @param[in][out] *NhltTableSize Size of created NHLT table
+
+ @retval EFI_SUCCESS NHLT created successfully
+ @retval EFI_BAD_BUFFER_SIZE Not enough resources to allocate NHLT
+**/
+EFI_STATUS
+NhltConstructor (
+ IN PCH_HDA_NHLT_ENDPOINTS *EndpointTable,
+ IN OUT NHLT_ACPI_TABLE **NhltTable,
+ IN OUT UINT32 *NhltTableSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT32 TableSize;
+ UINT32 EndpointDescriptorsLength;
+ UINT32 OedConfigLength;
+ NHLT_ACPI_TABLE *Table;
+
+
+ Status = EFI_SUCCESS;
+ TableSize = PCH_HDA_NHLT_TABLE_SIZE;
+ EndpointDescriptorsLength = 0;
+ OedConfigLength = 0;
+
+ Table = AllocateZeroPool (TableSize);
+
+ if (Table == NULL) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ Table->EndpointCount = 0;
+
+ for (Index = 0; Index < HdaEndpointMax; Index++) {
+ if (EndpointTable[Index].Enable == TRUE) {
+ EndpointDescriptorsLength += NhltEndpointConstructor (Table,
+ EndpointTable[Index].EndpointType,
+ EndpointTable[Index].EndpointFormatsBitmask,
+ Table->EndpointCount++);
+ }
+ }
+ DEBUG ((DEBUG_INFO, "NhltConstructor: EndpointCount = %d, All EndpointDescriptorsLength = %d B\n", Table->EndpointCount, EndpointDescriptorsLength));
+
+ OedConfigLength = NhltOedConfigConstructor (Table);
+ DEBUG ((DEBUG_INFO, "NhltConstructor: OedConfigLength = %d B\n", OedConfigLength));
+
+ TableSize = EndpointDescriptorsLength + OedConfigLength;
+
+ *NhltTableSize = TableSize;
+ *NhltTable = Table;
+
+ return Status;
+}
+
+/**
+ Constructs EFI_ACPI_DESCRIPTION_HEADER structure for NHLT table.
+
+ @param[in][out] *NhltTable NHLT table for which header will be created
+ @param[in] NhltTableSize Size of NHLT table
+
+ @retval None
+**/
+VOID
+NhltAcpiHeaderConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN UINT32 NhltTableSize
+ )
+{
+ DEBUG ((DEBUG_INFO, "NhltAcpiHeaderConstructor() Start\n"));
+
+ // Header
+ NhltTable->Header.Signature = NHLT_ACPI_TABLE_SIGNATURE;
+ NhltTable->Header.Length = (UINT32) (NhltTableSize + sizeof (NHLT_ACPI_TABLE) - sizeof (ENDPOINT_DESCRIPTOR) - sizeof (SPECIFIC_CONFIG));
+ NhltTable->Header.Revision = 0x0;
+ NhltTable->Header.Checksum = 0x0;
+
+ CopyMem (NhltTable->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (NhltTable->Header.OemId));
+ NhltTable->Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ NhltTable->Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
+ NhltTable->Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ NhltTable->Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ DEBUG ((DEBUG_INFO, "NhltAcpiHeaderConstructor(), NhltAcpiTable->Header.Length = %d B\n", NhltTable->Header.Length));
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c
new file mode 100644
index 0000000000..46096a0ac3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c
@@ -0,0 +1,336 @@
+/** @file
+ This file contains HD Audio NHLT Configuration BLOBs
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// DMIC Configuration BLOBs
+//
+// DMIC Config 2 channels, 16 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicStereo16BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00300003, 0x00300003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicStereo16BitFormatConfigSize = sizeof (DmicStereo16BitFormatConfig);
+
+// DMIC Config 2 channels, 32 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicStereo32BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00380003, 0x00380003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicStereo32BitFormatConfigSize = sizeof (DmicStereo32BitFormatConfig);
+
+// DMIC Config 4 channels, 16 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad16BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00320003, 0x00320003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicQuad16BitFormatConfigSize = sizeof (DmicQuad16BitFormatConfig);
+
+// DMIC Config 4 channels, 32 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad32BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x003a0003, 0x003a0003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicQuad32BitFormatConfigSize = sizeof (DmicQuad32BitFormatConfig);
+
+// DMIC Config 1 channel, 16 bits
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicMono16BitFormatConfig[] =
+{
+ 0x00000000,
+ 0xfffffff0,0xfffffff0,0xfffffff0,0xfffffff0,
+ 3,
+ 3,
+ 0x00300003,
+ 0x00300003,
+ 0x3,
+ 0x0, 0x09001303, 0x0, 0x0301, 0, 0, 0, 0,
+ 0x10, 0x402a0, 0, 0, 0, 0, 0, 0,
+ 0x10, 0xe03ae, 0, 0, 0, 0, 0, 0,
+ 0x00008, 0xfffae, 0xfff12, 0xffdfb, 0xffc61, 0xffa5a, 0xff82b, 0xff641, 0xff520, 0xff544, 0xff6f4, 0xffa25, 0xffe65,
+ 0x002e0, 0x0068f, 0x00876, 0x007f1, 0x004f5, 0x0002a, 0xffad4, 0xff68a, 0xff4bf, 0xff64f, 0xffb20,
+ 0x0020f, 0x00929, 0x00e2d, 0x00f40, 0x00b92, 0x003bf, 0xff9cd, 0xff0b0, 0xfeb6e, 0xfec2a, 0xff351,
+ 0xfff4f, 0x00ccd, 0x0179d, 0x01bfc, 0x017d7, 0x00ba3, 0xffa7e, 0xfe96f, 0xfddf5, 0xfdc4d, 0xfe5ee,
+ 0xff8ce, 0x00fb7, 0x023a8, 0x02df5, 0x02a74, 0x01910, 0xffe2c, 0xfe19c, 0xfcc64, 0xfc5ee, 0xfd17e,
+ 0xfecd4, 0x01071, 0x03198, 0x0457e, 0x044c9, 0x02e24, 0x00728, 0xfdb0e, 0xfb781, 0xfa86b, 0xfb408,
+ 0xfd884, 0x00c02, 0x03f37, 0x061e8, 0x06807, 0x04dc5, 0x01954, 0xfd98c, 0xfa1c8, 0xf840f, 0xf8b52,
+ 0xfb78c, 0xffd23, 0x047db, 0x080b1, 0x094e3, 0x07c08, 0x03b41, 0xfe45e, 0xf9101, 0xf5b1e, 0xf54f4,
+ 0xf8307, 0xfda0b, 0x0418f, 0x09ad0, 0x0c9d6, 0x0be16, 0x0780b, 0x009dd, 0xf92ba, 0xf3606, 0xf10ed,
+ 0xf315e, 0xf9135, 0x0172c, 0x09d83, 0x0fc9e, 0x11695, 0x0e05b, 0x065bf, 0xfc6ed, 0xf2ff4, 0xecc96,
+ 0xebbc9, 0xf0668, 0xf9be7, 0x05601, 0x1029e, 0x17140, 0x18065, 0x12728, 0x07874, 0xf9edb, 0xed202,
+ 0xe486c, 0xe294d, 0xe820f, 0xf424a, 0x03f29, 0x13d68, 0x1ff61, 0x253b2, 0x220fa, 0x16be1, 0x05638,
+ 0xf1798, 0xdf165, 0xd211a, 0xcd3f9, 0xd1eb5, 0xdfa89, 0xf4802, 0x0d656, 0x26d63, 0x3d808, 0x4ecc3,
+ 0x59315, 0x5c520, 0x58db6, 0x503d6, 0x444dd, 0x36ecb, 0x29b9a, 0x1de5d, 0x14234, 0x0cae0, 0x07669,
+ 0x03f40, 0x01e4e, 0x00c95, 0x0043b, 0x000f9,0xff961, 0x00823, 0x0084f, 0x00a39, 0x00d21, 0x010a8, 0x0149a, 0x018cc, 0x01d15, 0x0214d, 0x02543, 0x028c8, 0x02baa,
+ 0x02db8, 0x02ec6, 0x02eac, 0x02d4c, 0x02a90, 0x02672, 0x020f9, 0x01a3b, 0x0125c, 0x00994, 0x00025,
+ 0xff662, 0xfeca3, 0xfe34c, 0xfdabe, 0xfd364, 0xfcd94, 0xfc9a4, 0xfc7dd, 0xfc86b, 0xfcb6e, 0xfd0e6,
+ 0xfd8bb, 0xfe2b9, 0xfee8f, 0xffbd5, 0x00a0c, 0x018a3, 0x026fc, 0x03474, 0x04065, 0x04a36, 0x0515a,
+ 0x0555a, 0x055df, 0x052b2, 0x04bc3, 0x0412c, 0x03332, 0x02242, 0x00ef3, 0xff9fb, 0xfe430, 0xfce78,
+ 0xfb9c6, 0xfa70f, 0xf973a, 0xf8b1e, 0xf836e, 0xf80b7, 0xf8355, 0xf8b6e, 0xf98ea, 0xfab78, 0xfc288,
+ 0xfdd52, 0xffadf, 0x01a0a, 0x03992, 0x05823, 0x07465, 0x08d0c, 0x0a0e3, 0x0aedc, 0x0b61f, 0x0b614,
+ 0x0ae6b, 0x09f23, 0x0888d, 0x06b4c, 0x04850, 0x020d3, 0xff647, 0xfca4f, 0xf9eae, 0xf7533, 0xf4fa8,
+ 0xf2fc0, 0xf1702, 0xf06ba, 0xeffe6, 0xf032d, 0xf10d3, 0xf28b4, 0xf4a42, 0xf7486, 0xfa62a, 0xfdd81,
+ 0x01896, 0x0553d, 0x09128, 0x0c9fe, 0x0fd6f, 0x1294e, 0x14ba5, 0x162cb, 0x16d75, 0x16ac4, 0x15a52,
+ 0x13c38, 0x1110d, 0x0d9e9, 0x09856, 0x04e4a, 0xffe17, 0xfaa51, 0xf55c4, 0xf0350, 0xeb5d6, 0xe7020,
+ 0xe34c8, 0xe0620, 0xde61c, 0xdd64b, 0xdd7bd, 0xdeb03, 0xe102a, 0xe46b5, 0xe8dab, 0xee397, 0xf4699,
+ 0xfb479, 0x02ab3, 0x0a691, 0x1253c, 0x1a3d9, 0x21f98, 0x295cc, 0x30400, 0x36803, 0x3bff8, 0x40a63,
+ 0x44628, 0x4729b, 0x48f76, 0x49cd2, 0x49b35, 0x48b71, 0x46ea5, 0x44632, 0x413a6, 0x3d8b3, 0x3971b,
+ 0x350a6, 0x30716, 0x2bc15, 0x27131, 0x227cb, 0x1e11d, 0x19e2a, 0x15fc1, 0x1267c, 0x0f2c0, 0x0c4c2,
+ 0x09c8b, 0x079fb, 0x05cd2, 0x044b2, 0x0312d, 0x021c5, 0x015f4, 0x0135e,
+ 0x0, 0x09001303, 0x0, 0x0301, 0, 0, 0, 0,
+ 0x10, 0x402a0, 0, 0, 0, 0, 0, 0,
+ 0x10, 0xe03ae, 0, 0, 0, 0, 0, 0,
+ 0x00008, 0xfffae, 0xfff12, 0xffdfb, 0xffc61, 0xffa5a, 0xff82b, 0xff641, 0xff520, 0xff544, 0xff6f4, 0xffa25, 0xffe65,
+ 0x002e0, 0x0068f, 0x00876, 0x007f1, 0x004f5, 0x0002a, 0xffad4, 0xff68a, 0xff4bf, 0xff64f, 0xffb20,
+ 0x0020f, 0x00929, 0x00e2d, 0x00f40, 0x00b92, 0x003bf, 0xff9cd, 0xff0b0, 0xfeb6e, 0xfec2a, 0xff351,
+ 0xfff4f, 0x00ccd, 0x0179d, 0x01bfc, 0x017d7, 0x00ba3, 0xffa7e, 0xfe96f, 0xfddf5, 0xfdc4d, 0xfe5ee,
+ 0xff8ce, 0x00fb7, 0x023a8, 0x02df5, 0x02a74, 0x01910, 0xffe2c, 0xfe19c, 0xfcc64, 0xfc5ee, 0xfd17e,
+ 0xfecd4, 0x01071, 0x03198, 0x0457e, 0x044c9, 0x02e24, 0x00728, 0xfdb0e, 0xfb781, 0xfa86b, 0xfb408,
+ 0xfd884, 0x00c02, 0x03f37, 0x061e8, 0x06807, 0x04dc5, 0x01954, 0xfd98c, 0xfa1c8, 0xf840f, 0xf8b52,
+ 0xfb78c, 0xffd23, 0x047db, 0x080b1, 0x094e3, 0x07c08, 0x03b41, 0xfe45e, 0xf9101, 0xf5b1e, 0xf54f4,
+ 0xf8307, 0xfda0b, 0x0418f, 0x09ad0, 0x0c9d6, 0x0be16, 0x0780b, 0x009dd, 0xf92ba, 0xf3606, 0xf10ed,
+ 0xf315e, 0xf9135, 0x0172c, 0x09d83, 0x0fc9e, 0x11695, 0x0e05b, 0x065bf, 0xfc6ed, 0xf2ff4, 0xecc96,
+ 0xebbc9, 0xf0668, 0xf9be7, 0x05601, 0x1029e, 0x17140, 0x18065, 0x12728, 0x07874, 0xf9edb, 0xed202,
+ 0xe486c, 0xe294d, 0xe820f, 0xf424a, 0x03f29, 0x13d68, 0x1ff61, 0x253b2, 0x220fa, 0x16be1, 0x05638,
+ 0xf1798, 0xdf165, 0xd211a, 0xcd3f9, 0xd1eb5, 0xdfa89, 0xf4802, 0x0d656, 0x26d63, 0x3d808, 0x4ecc3,
+ 0x59315, 0x5c520, 0x58db6, 0x503d6, 0x444dd, 0x36ecb, 0x29b9a, 0x1de5d, 0x14234, 0x0cae0, 0x07669,
+ 0x03f40, 0x01e4e, 0x00c95, 0x0043b, 0x000f9,0xff961, 0x00823, 0x0084f, 0x00a39, 0x00d21, 0x010a8, 0x0149a, 0x018cc, 0x01d15, 0x0214d, 0x02543, 0x028c8, 0x02baa,
+ 0x02db8, 0x02ec6, 0x02eac, 0x02d4c, 0x02a90, 0x02672, 0x020f9, 0x01a3b, 0x0125c, 0x00994, 0x00025,
+ 0xff662, 0xfeca3, 0xfe34c, 0xfdabe, 0xfd364, 0xfcd94, 0xfc9a4, 0xfc7dd, 0xfc86b, 0xfcb6e, 0xfd0e6,
+ 0xfd8bb, 0xfe2b9, 0xfee8f, 0xffbd5, 0x00a0c, 0x018a3, 0x026fc, 0x03474, 0x04065, 0x04a36, 0x0515a,
+ 0x0555a, 0x055df, 0x052b2, 0x04bc3, 0x0412c, 0x03332, 0x02242, 0x00ef3, 0xff9fb, 0xfe430, 0xfce78,
+ 0xfb9c6, 0xfa70f, 0xf973a, 0xf8b1e, 0xf836e, 0xf80b7, 0xf8355, 0xf8b6e, 0xf98ea, 0xfab78, 0xfc288,
+ 0xfdd52, 0xffadf, 0x01a0a, 0x03992, 0x05823, 0x07465, 0x08d0c, 0x0a0e3, 0x0aedc, 0x0b61f, 0x0b614,
+ 0x0ae6b, 0x09f23, 0x0888d, 0x06b4c, 0x04850, 0x020d3, 0xff647, 0xfca4f, 0xf9eae, 0xf7533, 0xf4fa8,
+ 0xf2fc0, 0xf1702, 0xf06ba, 0xeffe6, 0xf032d, 0xf10d3, 0xf28b4, 0xf4a42, 0xf7486, 0xfa62a, 0xfdd81,
+ 0x01896, 0x0553d, 0x09128, 0x0c9fe, 0x0fd6f, 0x1294e, 0x14ba5, 0x162cb, 0x16d75, 0x16ac4, 0x15a52,
+ 0x13c38, 0x1110d, 0x0d9e9, 0x09856, 0x04e4a, 0xffe17, 0xfaa51, 0xf55c4, 0xf0350, 0xeb5d6, 0xe7020,
+ 0xe34c8, 0xe0620, 0xde61c, 0xdd64b, 0xdd7bd, 0xdeb03, 0xe102a, 0xe46b5, 0xe8dab, 0xee397, 0xf4699,
+ 0xfb479, 0x02ab3, 0x0a691, 0x1253c, 0x1a3d9, 0x21f98, 0x295cc, 0x30400, 0x36803, 0x3bff8, 0x40a63,
+ 0x44628, 0x4729b, 0x48f76, 0x49cd2, 0x49b35, 0x48b71, 0x46ea5, 0x44632, 0x413a6, 0x3d8b3, 0x3971b,
+ 0x350a6, 0x30716, 0x2bc15, 0x27131, 0x227cb, 0x1e11d, 0x19e2a, 0x15fc1, 0x1267c, 0x0f2c0, 0x0c4c2,
+ 0x09c8b, 0x079fb, 0x05cd2, 0x044b2, 0x0312d, 0x021c5, 0x015f4, 0x0135e
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicMono16BitFormatConfigSize = sizeof (DmicMono16BitFormatConfig);
+
+//
+// I2S Configuration BLOBs
+// Audio Format and Configuration details
+//
+// Frequency: 48kHz, PCM resolution: 24 bits
+// TDM slots: 4
+// Codec: Realtek ALC298, mode: slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfig[] = {0x0, 0xffffff10, 0xffffff32, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0x83d00437, 0xc0700000, 0x0, 0x02010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x00000001, 0x00000fff};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfigSize = sizeof (I2sRtk298Render4ch48kHz24bitFormatConfig);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfig[] = {0x0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x83d00437, 0xc0700000, 0x0, 0x02010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x00000001, 0x00000fff};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfigSize = sizeof (I2sRtk298Capture4ch48kHz24bitFormatConfig);
+
+// Audio Format: 48kHz, 2channels, master clock
+// Codec: Realtek ALC286S
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk286S2ch48kHzFormatConfig[] = { 0, 0xffffff10, 0xffffff32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x83d00437, 0xc0700000, 0x0, 0x2990000, 0xf, 0xf, 0x4002, 0x0, 0x7070f00, 0x20, 0x1, 0xfff };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk286S2ch48kHzFormatConfigSize = sizeof (I2sRtk286S2ch48kHzFormatConfig);
+
+// Audio Format: 48kHz, 4 channels
+// Codec: ADI SSM4567
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sAdi4ch48kHzFormatConfig[] = { 0, 0xffffff10, 0xffffff32, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0x83d00437, 0xc0700000, 0x0, 0x2010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0, 0 };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sAdi4ch48kHzFormatConfigSize = sizeof (I2sAdi4ch48kHzFormatConfig);
+
+// Audio Format: 24bit, 48kHz, Master
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2s48kHz24bitMasterFormatConfig[] = { 0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x81d00937, 0xc0700000, 0x0, 0x02990000, 0x3, 0x3, 0x4002, 0x0, 0x7070f00, 0x20, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2s48kHz24bitMasterFormatConfigSize = sizeof (I2s48kHz24bitMasterFormatConfig);
+
+// Audio Format: 24bit, 48kHz, Slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2s48kHz24bitSlaveFormatConfig[] = { 0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x81d00037, 0xd3700000, 0x0, 0x02000000, 0x3, 0x3, 0x4002, 0x0, 0x7070f00, 0x00, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2s48kHz24bitSlaveFormatConfigSize = sizeof (I2s48kHz24bitSlaveFormatConfig);
+
+// Audio Format: PCM 16bit, 8kHz, Master
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sPcm8kHz16bitMasterFormatConfig[] = { 0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0x80c0953f, 0xc0400000, 0x0, 0x02010004, 0x1, 0x1, 0x4002, 0x4, 0x7020000, 0x20, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sPcm8kHz16bitMasterFormatConfigSize = sizeof (I2sPcm8kHz16bitMasterFormatConfig);
+
+// Audio Format: PCM 16bit, 8kHz, Slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfig[] = { 0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0x80c0003f, 0xd3400000, 0x0, 0x02000004, 0x1, 0x1, 0x4002, 0x0, 0x7020000, 0x00, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfigSize = sizeof (I2sPcm8kHz16bitSlaveFormatConfig);
+
+//
+// BlueTooth Configuration BLOBs
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 BtFormatConfig[] =
+{
+ 0x0, 0xfffffff0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x80c0003f, 0xd3400000, 0x0, 0x02000005, 0x01, 0x01, 0x4002,
+ 0x0, 0x07020000, 0x0, 0x01, 0x0
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BtFormatConfigSize = sizeof (BtFormatConfig);
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c
new file mode 100644
index 0000000000..32814bf773
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c
@@ -0,0 +1,545 @@
+/** @file
+ Implement the I2C controller driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Base.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+#include <PchAccess.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/I2cMaster.h>
+#include <Pi/PiI2c.h>
+#include <Library/DevicePathLib.h>
+#include <Library/I2cMasterCommonLib.h>
+
+/**
+ Prepare I2c controller for use: enable its mmio range, put in D0, get out of reset
+
+ @param[in] Context - driver context
+**/
+VOID
+PrepareController (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ MmioOr32 (Context->ConfigAddress + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ MmioAnd32 (Context->ConfigAddress + R_PCH_SERIAL_IO_PME_CTRL_STS, (UINT32) (~B_PCH_SERIAL_IO_PME_CTRL_STS_PWR_ST));
+ MmioOr32 (Context->MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+}
+
+/**
+ Determine the state of the I2C controller
+
+ @param[in] Context - driver context
+
+ @retval TRUE The I2C controller is active
+ @retval FALSE The I2C controller is idle
+**/
+BOOLEAN
+IsHardwareActive (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ return (MmioRead32 (Context->MmioAddress + R_IC_STATUS) & B_IC_STATUS_ACTIVITY );
+}
+
+/**
+ Updates WriteOperation and WritePosition, two variables that determine
+ which part of Request is being committed to I2C bus.
+ This iterates over both Read and Write operations from a request, because
+ things that need to be written to WriteFifo are both I2c bus writes
+ and I2c bus reads (the command to perform bus read needs to be put into Write Fifo)
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateWritePosition (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ( Context->WritePos == Context->Request->Operation[Context->WriteOp].LengthInBytes - 1) {
+ Context->WritePos = 0;
+ Context->WriteOp ++;
+ } else {
+ Context->WritePos ++;
+ }
+}
+
+/*
+ FindReadOp checks if current Operation is of Read type. If so, returns.
+ If not, increases ReadOp until it finds one or goes beyond Request's OperationCount
+
+ @param[in] Context - driver context
+*/
+VOID
+FindReadOp (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ while (Context->ReadOp < Context->Request->OperationCount &&
+ !(Context->Request->Operation[Context->ReadOp].Flags & I2C_FLAG_READ)) {
+ Context->ReadOp++;
+ }
+}
+
+/**
+ Updates ReadOperation and ReadPosition, two variables that determine
+ which part of Request is being filled with data incoming from I2C reads.
+ This iterates only over Read operations from a request.
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateReadPosition (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ( Context->ReadPos == Context->Request->Operation[Context->ReadOp].LengthInBytes - 1) {
+ Context->ReadPos = 0;
+ Context->ReadOp ++;
+ FindReadOp (Context);
+ } else {
+ Context->ReadPos ++;
+ }
+}
+
+/**
+ ValidateRequest checks if Request is valid and can be started
+
+ @param[in] Context - driver context
+ @param[in] RequestPacket
+
+ @retval EFI_SUCCESS Request is valid and can be started
+ @retval EFI_ALREADY_STARTED The controller is busy with another transfer
+ @retval EFI_BAD_BUFFER_SIZE Transfer size too big
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL, invalid Operation flags
+ @retval EFI_UNSUPPORTED "ping" operation attempted (0-byte transfer, address byte not followed by any data)
+**/
+EFI_STATUS
+ValidateRequest (
+ I2C_MASTER_CONTEXT *Context,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ )
+{
+ UINTN TotalSize;
+ UINTN Operation;
+ UINTN OperationSize;
+
+ if (Context->TransferInProgress) {
+ return EFI_ALREADY_STARTED;
+ }
+ if (RequestPacket == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RequestPacket->OperationCount == 0) {
+ // 0-size operations ("pings") not supported
+ return EFI_UNSUPPORTED;
+ }
+
+ TotalSize = 0;
+
+ for (Operation=0; Operation < RequestPacket->OperationCount; Operation++) {
+ // unsupported flags?
+ if ((RequestPacket->Operation[Operation].Flags & (~I2C_FLAG_READ)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ OperationSize = RequestPacket->Operation[Operation].LengthInBytes;
+ // 0-size operations ("pings") not supported
+ if (OperationSize == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ TotalSize += OperationSize;
+ // read operation too big?
+ if (RequestPacket->Operation[Operation].Flags & I2C_FLAG_READ) {
+ if (OperationSize > Context->Capabilities.MaximumReceiveBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ // write operation too big?
+ } else {
+ if (OperationSize > Context->Capabilities.MaximumTransmitBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ }
+ }
+ // total request too big?
+ if (TotalSize > Context->Capabilities.MaximumTotalBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ IsLastFromRequest checks if WritePos and WriteOp point to the last byte of the request
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsLastFromRequest (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ((Context->WriteOp == Context->Request->OperationCount - 1 ) &&
+ (Context->WritePos == Context->Request->Operation[Context->WriteOp].LengthInBytes - 1)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ IsFirstFromOperation checks if WritePos and WriteOp point to the first byte of an operation
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsFirstFromOperation (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ((Context->WriteOp != 0) && (Context->WritePos == 0)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ InitializeTransfer checks if HW is ready to accept new transfer.
+ If so, sets up slave address
+
+ @param[in] Context - driver context
+
+ @retval Status
+**/
+EFI_STATUS
+InitializeTransfer (
+ I2C_MASTER_CONTEXT *Context,
+ UINTN SlaveAddress,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ )
+{
+ UINT32 Attempts = 10000;
+ UINT32 Address;
+
+ Context->Request = (EFI_I2C_REQUEST_PACKET*) RequestPacket;
+ Context->TransferStatus = EFI_SUCCESS;
+ Context->WriteOp = 0;
+ Context->WritePos = 0;
+ Context->ReadOp = 0;
+ FindReadOp (Context);
+ Context->ReadPos = 0;
+
+ if (MmioRead32 (Context->MmioAddress + R_IC_ENABLE) != 0) {
+ DEBUG (( DEBUG_ERROR, "Address change was attempted while a transfer was underway!\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Address = SlaveAddress & 0xFF;
+ if (SlaveAddress & I2C_ADDRESSING_10_BIT
+ ) {
+ Address |= B_IC_TAR_10BITADDR_MASTER;
+ }
+ MmioWrite32 (Context->MmioAddress + R_IC_TAR, Address);
+ MmioWrite32 (Context->MmioAddress + R_IC_ENABLE, B_IC_EN );
+ //clear errors
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_TX_ABRT);
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_INTR);
+
+ while ( !(MmioRead32 (Context->MmioAddress + R_IC_ENABLE_STATUS ) & B_IC_EN)) {
+ //should never happen, but just to make sure BIOS doesn't hang in infinite loop...
+ MicroSecondDelay (1);
+ if (--Attempts == 0) {
+ MmioWrite32 (Context->MmioAddress + R_IC_ENABLE, 0 );
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ Context->TransferInProgress = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ WriteFifo writes to I2c controller's transmit Fifo. Data written to Fifo could be
+ - data bytes to be written to an i2c slave
+ - read requests that trigger i2c bus reads
+ First transfer from each operation adds Restart bit which triggers Restart condition on bus
+ Last transfer from the whole Request adds Stop bit which triggers Stop condtion on bus
+ Driver keeps track of which parts of Request were already committed to hardware using
+ pointer consisting of WritePosition and WriteOperation variables. This pointer is updated
+ every time data byte/read request is committed to FIFO
+ WriteFifo executes while there's anything more to write and the write fifo isn't full
+
+ @param[in] Context - driver context
+**/
+VOID
+WriteFifo (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ UINT32 Data;
+ while ( MmioRead32 (Context->MmioAddress + R_IC_STATUS ) & B_IC_STATUS_TFNF) {
+ if (Context->WriteOp >= Context->Request->OperationCount ) {
+ return; // request complete, nothing more to write
+ }
+
+ if (Context->Request->Operation[Context->WriteOp].Flags & I2C_FLAG_READ) {
+ Data = B_IC_CMD_READ;
+ } else {
+ Data = Context->Request->Operation[Context->WriteOp].Buffer[Context->WritePos];
+ }
+ if (IsLastFromRequest (Context)) {
+ Data |= B_IC_CMD_STOP;
+ }
+ if (IsFirstFromOperation (Context)) {
+ Data |= B_IC_CMD_RESTART;
+ }
+ MmioWrite32 (Context->MmioAddress + R_IC_DATA_CMD, Data);
+ UpdateWritePosition (Context);
+ }
+}
+
+/**
+ ReadFifo reads from I2c controller's receive Fifo. It contains data retrieved
+ from slave device as a result of executing read transfers, which were
+ triggered by putting read requests into Write Fifo. Retrieved data is copied into buffers
+ pointed to by Request structure.
+ Driver keeps track where to copy incoming data using pointer consisting of
+ ReadPosition and ReadOperation variables. This pointer is updated
+ every time data was retrieved from hardware
+ ReadFifo executes while there's data available and receive buffers were not filled
+
+ @param[in] Context - driver context
+**/
+VOID
+ReadFifo (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ while ( MmioRead32 ( Context->MmioAddress + R_IC_STATUS ) & B_IC_STATUS_RFNE) {
+ if ( Context->ReadOp >= Context->Request->OperationCount ) {
+ return;
+ }
+ Context->Request->Operation[Context->ReadOp].Buffer[Context->ReadPos] = (0xFF & MmioRead32 (Context->MmioAddress + R_IC_DATA_CMD));
+ UpdateReadPosition (Context);
+ }
+}
+
+/**
+ CheckErrors checks if there were any transfer errors.
+
+ @param[in] Context - driver context
+**/
+VOID
+CheckErrors (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (!(MmioRead32 (Context->MmioAddress + R_IC_INTR_STAT) & B_IC_INTR_TX_ABRT)) {
+ return;
+ }
+ if (MmioRead32 (Context->MmioAddress + R_IC_TX_ABRT_SOURCE) & B_IC_TX_ABRT_7B_ADDR_NACK) {
+ Context->TransferStatus = EFI_NO_RESPONSE;
+ } else {
+ Context->TransferStatus = EFI_DEVICE_ERROR;
+ }
+ DEBUG (( DEBUG_INFO, "I2c CheckErrors: %08x\n", MmioRead32 (Context->MmioAddress + R_IC_TX_ABRT_SOURCE)));
+}
+
+/**
+ Transfer is finished when all requested operations were placed in fifo,
+ all read requests were filled and hardware is inactive
+ The last part is necessary for write-only transfers where after
+ placing all writes in fifo sw needs to wait until they flush down the bus
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsTransferFinished (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (( Context->WriteOp >= Context->Request->OperationCount ) &&
+ ( Context->ReadOp >= Context->Request->OperationCount ) &&
+ !IsHardwareActive (Context)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ Clean up Hw activity and errors
+ Return status to Request's submitter and signal the event that tells
+ it that the request is complete
+ Clear up Sw context to allow new request to start
+
+ @param[in] Context - driver context
+*/
+VOID
+FinishTransfer (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ UINT32 Attempts = 10000;
+
+ MmioWrite32 ( Context->MmioAddress + R_IC_ENABLE, 0 );
+
+ while ( MmioRead32 ( Context->MmioAddress + R_IC_ENABLE_STATUS ) & B_IC_EN ) {
+ //try for 1ms; should take no more than 100us even at slowest bus speed, but just to make sure BIOS doesn't hang in infinite loop
+ MicroSecondDelay ( 1 );
+ if (--Attempts == 0) {
+ ASSERT (FALSE);
+ break;
+ }
+ }
+
+ //
+ //clear errors
+ //
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_TX_ABRT);
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_INTR);
+
+ //
+ //clean up context data
+ //
+ Context->TransferInProgress = FALSE;
+}
+
+/**
+ PerformTransfer. For synchronous transfer this function is called in a loop
+ and for asynchronous transfers, as a timer callback. It writes data and/or
+ read requests to hadrware, copies read data to destination buffers. When
+ transfer completes, it cleans up Sw context and Hw registers in preparation
+ for new transfer
+
+ @param[in] Context - driver context
+**/
+VOID
+PerformTransfer (
+ IN I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (!Context->TransferInProgress) {
+ return;
+ }
+ if (EFI_ERROR (Context->TransferStatus) || IsTransferFinished (Context)) {
+ FinishTransfer (Context);
+ return;
+ }
+ WriteFifo (Context);
+ ReadFifo (Context);
+ CheckErrors (Context);
+}
+
+
+/**
+ Set the I2C controller bus clock frequency.
+
+ This routine must be called at or below TPL_NOTIFY.
+
+ The software and controller do a best case effort of using the specified
+ frequency for the I2C bus. If the frequency does not match exactly then
+ the controller will use lower frequency for the I2C to avoid exceeding
+ the operating conditions for any of the I2C devices on the bus.
+ For example if 400 KHz was specified and the controller's divide network
+ only supports 402 KHz or 398 KHz then the controller would be set to 398
+ KHz.
+
+ @param[in] MmioAddress Address of I2C controller
+ @param[in] BusClockHertz New I2C bus clock frequency in Hertz
+
+ @retval EFI_SUCCESS The bus frequency was set successfully.
+ @retval EFI_UNSUPPORTED The controller does not support this frequency.
+**/
+
+EFI_STATUS
+FrequencySet (
+ IN UINTN MmioAddress,
+ IN OUT UINTN *BusClockHertz
+ )
+{
+ UINT32 Speed;
+
+ if ( *BusClockHertz < 100*1000) {
+ //can't run that slowly
+ return EFI_UNSUPPORTED;
+ } else if ( *BusClockHertz < 400*1000) {
+ //for any request in range [100kHz, 400kHz), set 100kHz
+ *BusClockHertz = 100000;
+ Speed = V_IC_SPEED_STANDARD;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x001C001C);
+ MmioWrite32 ( MmioAddress + R_IC_SS_SCL_HCNT, 528);
+ MmioWrite32 ( MmioAddress + R_IC_SS_SCL_LCNT, 640);
+ } else if ( *BusClockHertz < 1000*1000) {
+ //for any request in range [400kHz, 1MHz), set 400kHz
+ *BusClockHertz = 400000;
+ Speed = V_IC_SPEED_FAST;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x001C001C);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_HCNT, 128);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_LCNT, 160);
+ } else {
+ //for any request in range [1MHz, +inf), set 1MHz. This silicon doesn't support 3.4MHz mode.
+ *BusClockHertz = 1000000;
+ Speed = V_IC_SPEED_FAST;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x00280028);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_HCNT, 30);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_LCNT, 80);
+ }
+
+ MmioWrite32 ( MmioAddress + R_IC_CON, Speed | B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_IC_MASTER_MODE);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset the I2C controller
+
+ @param[in] MmioAddress Address of I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+I2cReset (
+ IN UINTN MmioAddress
+ )
+{
+ MmioAnd32 (
+ MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ (UINT32) ~(B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA)
+ );
+ MmioRead32 (MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS);
+ MmioOr32 (
+ MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA
+ );
+ MmioRead32 (MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS);
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf
new file mode 100644
index 0000000000..a6af85a4a0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for the I2C port driver.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeI2cMasterCommonLib
+FILE_GUID = D0E4E669-D467-42af-93D8-21513E226EEA
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = I2cMasterCommonLib
+
+
+[LibraryClasses]
+DebugLib
+PchSerialIoLib
+MmPciLib
+IoLib
+PciLib
+MmPciLib
+TimerLib
+PchInfoLib
+
+
+[Packages]
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+MdePkg/MdePkg.dec
+
+
+[Sources]
+I2cMasterCommonLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
new file mode 100644
index 0000000000..89bf0a73ee
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
@@ -0,0 +1,305 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific purpose
+ used by Reference Code only.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/PchInfoLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+
+//
+// Chipset specific data
+//
+//ISH
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[PCH_ISH_MAX_GP_PINS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshGPGpio[PCH_ISH_MAX_GP_PINS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER];
+
+
+//PCIe SRCCLKREQB
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpPcieSrcClkReqbPinToGpioMap[PCH_LP_PCIE_MAX_CLK_REQ];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHPcieSrcClkReqbPinToGpioMap[PCH_H_PCIE_MAX_CLK_REQ];
+
+//PCH_HOT
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin;
+extern GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin;
+
+//CPU GP
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[4];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHCpuGpPinMap[4];
+
+/**
+ This function sets ISH I2C controller pins into native mode
+
+ @param[in] IshI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshI2cPinsIntoNativeMode (
+ IN UINT32 IshI2cControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_ISH_PINS_PER_I2C_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ I2cGpio = mPchLpIshI2cGpio;
+ } else {
+ I2cGpio = mPchHIshI2cGpio;
+ }
+
+ ASSERT (IshI2cControllerNumber < PCH_ISH_MAX_I2C_CONTROLLERS);
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_I2C_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (I2cGpio[IshI2cControllerNumber][Index].Pad, I2cGpio[IshI2cControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH UART controller pins into native mode
+
+ @param[in] IshUartControllerNumber UART controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshUartPinsIntoNativeMode (
+ IN UINT32 IshUartControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*UartGpio) [PCH_ISH_PINS_PER_UART_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ UartGpio = mPchLpIshUartGpio;
+ } else {
+ UartGpio = mPchHIshUartGpio;
+ }
+
+ ASSERT (IshUartControllerNumber < PCH_ISH_MAX_UART_CONTROLLERS);
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_UART_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (UartGpio[IshUartControllerNumber][Index].Pad, UartGpio[IshUartControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH SPI controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshSpiPinsIntoNativeMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SpiGpio;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ SpiGpio = mPchLpIshSpiGpio;
+ } else {
+ SpiGpio = mPchHIshSpiGpio;
+ }
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_SPI_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (SpiGpio[Index].Pad, SpiGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH GP pins into native mode
+
+ @param[in] IshGpPinNumber ISH GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshGpPinsIntoNativeMode (
+ IN UINT32 IshGpPinNumber
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION *IshGp;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ IshGp = mPchLpIshGPGpio;
+ } else {
+ IshGp = mPchHIshGPGpio;
+ }
+ ASSERT (IshGpPinNumber < PCH_ISH_MAX_GP_PINS);
+
+ Status = SetGpioPadMode (IshGp[IshGpPinNumber].Pad, IshGp[IshGpPinNumber].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+/**
+ Returns a pad for given CLKREQ# index.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return CLKREQ# pad.
+**/
+GPIO_PAD
+GpioGetClkreqPad (
+ IN UINT32 ClkreqIndex
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
+ return mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ } else {
+ ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
+ return mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ }
+}
+
+/**
+ Enables CLKREQ# pad in native mode.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return none
+**/
+VOID
+GpioEnableClkreq (
+ IN UINT32 ClkreqIndex
+ )
+{
+ GPIO_CONFIG PadConfig;
+ GPIO_PAD ClkreqPad;
+ GPIO_PAD_MODE PadMode;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
+ ClkreqPad = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ PadMode = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
+ } else {
+ ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
+ ClkreqPad = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ PadMode = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
+ }
+
+ PadConfig.PadMode = PadMode;
+ PadConfig.Direction = GpioDirNone;
+ PadConfig.PowerConfig = GpioHostDeepReset;
+ DEBUG ((DEBUG_INFO, "Enabling CLKREQ%d\n", ClkreqIndex));
+ GpioSetPadConfig (ClkreqPad, &PadConfig);
+}
+
+/**
+ This function checks if GPIO pin for PCHHOTB is in NATIVE MODE
+
+ @param[in] none
+
+ @retval TRUE Pin is in PCHHOTB native mode
+ FALSE Pin is in gpio mode or is not owned by HOST
+**/
+BOOLEAN
+GpioIsPchHotbPinInNativeMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION PchHotbPin;
+ GPIO_PAD_MODE GpioMode;
+
+
+ if (GetPchSeries () == PchLp) {
+ PchHotbPin = mPchLpPchHotbPin;
+ } else {
+ PchHotbPin = mPchHPchHotbPin;
+ }
+
+ Status = GetGpioPadMode (PchHotbPin.Pad, &GpioMode);
+
+ if ((EFI_ERROR (Status)) || (GpioMode != PchHotbPin.Mode)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ This function sets CPU GP pins into native mode
+
+ @param[in] CpuGpPinNum CPU GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCpuGpPinsIntoNativeMode (
+ IN UINT32 CpuGpPinNum
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION *CpuGpPins;
+
+ if (GetPchSeries () == PchLp) {
+ CpuGpPins = mPchLpCpuGpPinMap;
+ } else {
+ CpuGpPins = mPchHCpuGpPinMap;
+ }
+
+ ASSERT (CpuGpPinNum < 4);
+
+ Status = SetGpioPadMode (CpuGpPins[CpuGpPinNum].Pad, CpuGpPins[CpuGpPinNum].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
new file mode 100644
index 0000000000..b386e071f7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
@@ -0,0 +1,318 @@
+/** @file
+ This file contains GPIO routines for RC usage
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+/**
+ This procedure will get value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[out] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ OUT UINT32 *RegVal
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINTN GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *RegVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[in] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ IN UINT32 RegVal
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINTN GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset), RegVal);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI. Relation between Index and GpioPad number is:
+ Index = GpioGroup + 24 * GpioPad
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiSmiEnRegAddress Address of GPI SMI Enable register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiSmiEnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroupOffset;
+ UINTN GpioGroupInfoLength;
+ UINT32 SmiRegOffset;
+
+ GPIO_PAD_OWN PadOwnVal;
+ UINT32 HostOwnVal;
+
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+
+ PadNumber = 0;
+ GroupIndex = 0;
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ PadNumber = Index;
+ if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) {
+ //
+ // Found group and pad number
+ //
+ break;
+ }
+ Index = Index - GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if selected group has GPI SMI Enable and Status registers
+ //
+ if (GpioGroupInfo[GroupIndex].SmiEnOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH/IE
+ //
+ GpioGetPadOwnership (GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber), &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n",GroupIndex, PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if Host Software Pad Ownership is set to ACPI Mode
+ //
+ GpioGetHostSwOwnershipForPad (GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber), &HostOwnVal);
+ if (HostOwnVal != V_PCH_PCR_GPIO_HOSTSW_OWN_ACPI) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_END ();
+
+ *GpioPin = GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber);
+ *GpiSmiBitOffset = (UINT8)(PadNumber % 32);
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiEnRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiStsRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear GPIO_UNLOCK_SMI_STS
+
+ @param[in] None
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearUnlockSmiSts (
+ VOID
+ )
+{
+ UINT16 AcpiBaseAddr;
+
+ PchAcpiBaseGet (&AcpiBaseAddr);
+
+ //
+ // GPIO_UNLOCK_SMI_STS is cleared by writing 1 to it. Other bits in
+ // R_PCH_SMI_STS registers are either RO or RW/1C so writing 0 to them
+ // will not change their state.
+ //
+ IoWrite32 (AcpiBaseAddr + R_PCH_SMI_STS, B_PCH_SMI_STS_GPIO_UNLOCK);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will set GPIO Driver IRQ number
+
+ @param[in] Irq Irq number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid IRQ number
+**/
+EFI_STATUS
+GpioSetIrq (
+ IN UINT8 Irq
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ //
+ // Check if Irq is 14 or 15
+ //
+ if ((Irq < 14) || (Irq > 15)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data32And = (UINT32) ~(B_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE);
+ Data32Or = (UINT32) (Irq - 14) << N_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE;
+
+ //
+ // Program MISCCFG register for Community 0
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM0, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 1
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM1, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 2
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM2, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 3
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM3, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will perform special handling of GPP_A_12 on PCH-LP.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GpioA12SpecialHandling (
+ VOID
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+
+ //
+ // SKL PCH BWG 16.6. PCH-LP GPP_A_12 Special Handling
+ //
+ if (GetPchSeries () == PchLp) {
+ GpioGetPadOwnership (GPIO_SKL_LP_GPP_A12, &PadOwnVal);
+
+ //
+ // If the pad is host-own, BIOS has to always lock this pad after being initialized
+ //
+ if (PadOwnVal == GpioPadOwnHost) {
+ //
+ // Set PadCfgLock for GPP_A_12
+ //
+ GpioLockPadCfg (GPIO_SKL_LP_GPP_A12);
+ }
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c
new file mode 100644
index 0000000000..3d8b128a1c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c
@@ -0,0 +1,200 @@
+/** @file
+ This file contains SKL specific GPIO information
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+
+//
+// ISH GP pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[PCH_ISH_MAX_GP_PINS] =
+{
+ {GPIO_SKL_LP_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_SKL_LP_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_SKL_LP_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_SKL_LP_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_SKL_LP_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_SKL_LP_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_SKL_LP_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_SKL_LP_GPP_A17, GpioPadModeNative2} // ISH_GP_7
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshGPGpio[PCH_ISH_MAX_GP_PINS] =
+{
+ {GPIO_SKL_H_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_SKL_H_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_SKL_H_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_SKL_H_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_SKL_H_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_SKL_H_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_SKL_H_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_SKL_H_GPP_A17, GpioPadModeNative1} // ISH_GP_7
+};
+//
+// ISH UART controller pins
+// ISH UART[controller number][pin: RXD/TXD/RTSB/CTSB]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { //UART0
+ {GPIO_SKL_LP_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_SKL_LP_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_SKL_LP_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_SKL_LP_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { //UART1
+ {GPIO_SKL_LP_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_SKL_LP_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_SKL_LP_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTSB
+ {GPIO_SKL_LP_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTSB
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { //UART0
+ {GPIO_SKL_H_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_SKL_H_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_SKL_H_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_SKL_H_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { //UART1
+ {GPIO_SKL_H_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_SKL_H_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_SKL_H_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTS
+ {GPIO_SKL_H_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTS
+ }
+};
+
+//
+// ISH I2C controller pins
+// ISH I2C[controller number][pin: SDA/SCL]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { //I2C0
+ {GPIO_SKL_LP_GPP_D5, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_SKL_LP_GPP_D6, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { //I2C1
+ {GPIO_SKL_LP_GPP_D7, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_SKL_LP_GPP_D8, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { //I2C2
+ {GPIO_SKL_LP_GPP_F10, GpioPadModeNative2},// ISH_I2C2_SDA
+ {GPIO_SKL_LP_GPP_F11, GpioPadModeNative2} // ISH_I2C2_SCL
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { //I2C0
+ {GPIO_SKL_H_GPP_H19, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_SKL_H_GPP_H20, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { //I2C1
+ {GPIO_SKL_H_GPP_H21, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_SKL_H_GPP_H22, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { //I2C2
+ {GPIO_SKL_H_GPP_D4, GpioPadModeNative1},// ISH_I2C2_SDA
+ {GPIO_SKL_H_GPP_D23, GpioPadModeNative1} // ISH_I2C2_SCL
+ }
+};
+
+//
+// ISH SPI controller pins
+// ISH SPI[pin: CSB/CLK/MISO/MOSI]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_SKL_LP_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_SKL_LP_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_SKL_LP_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_SKL_LP_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_SKL_H_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_SKL_H_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_SKL_H_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_SKL_H_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+//
+// GPIO pin for PCIE SCRCLKREQB
+// SCRCLKREQB_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPcieSrcClkReqbPinToGpioMap[PCH_LP_PCIE_MAX_CLK_REQ] =
+{
+ {GPIO_SKL_LP_GPP_B5, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B6, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B7, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B8, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B9, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B10, GpioPadModeNative1}
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPcieSrcClkReqbPinToGpioMap[PCH_H_PCIE_MAX_CLK_REQ] =
+{
+ {GPIO_SKL_H_GPP_B5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B9, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B10, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H0, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H1, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H2, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H3, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H4, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H9, GpioPadModeNative1}
+};
+
+//
+// PCHHOTB pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin = {GPIO_SKL_LP_GPP_B23, GpioPadModeNative2};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin = {GPIO_SKL_H_GPP_B23, GpioPadModeNative2};
+
+//
+// CPU GP pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[4] =
+{
+ {GPIO_SKL_LP_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_SKL_LP_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_SKL_LP_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_SKL_LP_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCpuGpPinMap[4] =
+{
+ {GPIO_SKL_H_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_SKL_H_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_SKL_H_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_SKL_H_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf
new file mode 100644
index 0000000000..d2542a1673
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for the PeiDxeSmmGpioPrivateLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmGpioPrivateLib
+FILE_GUID = E078A734-BEA0-47CF-A476-3742316D01FC
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchCycleDecodingLib
+ PchInfoLib
+ GpioLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+ GpioPrivateLib.c
+ GpioNativePrivateLib.c
+ PchSklGpioPrivateData.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
new file mode 100644
index 0000000000..a49bbc5c18
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
@@ -0,0 +1,519 @@
+/** @file
+ Pch common library for PCH INIT PEI/DXE/SMM modules
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <PchPolicyCommon.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/TimerLib.h>
+
+extern CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[];
+extern CONST UINT32 mPchPcieControllerInfoSize;
+
+#define PORT_PLS_TIMEOUT 100 ///< 100 * 10 us = 1ms timeout for USB3 PortSC PLS polling
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ )
+{
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].Pid;
+}
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpIndex Root Port Index (0-based)
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpIndex
+ )
+{
+ return PchGetPcieControllerSbiPid ((UINT32) (RpIndex / PCH_PCIE_CONTROLLER_PORTS));
+}
+
+/**
+ Calculate root port device number based on physical port index.
+
+ @param[in] RpIndex Root port index (0-based).
+
+ @retval Root port device number.
+**/
+UINT32
+PchGetPcieRpDevice (
+ IN UINT32 RpIndex
+ )
+{
+ UINTN ControllerIndex;
+ ControllerIndex = RpIndex / PCH_PCIE_CONTROLLER_PORTS;
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].DevNum;
+}
+
+/**
+ This function reads Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[out] *Data32 Value of Config register
+
+ @retval EFI_SUCCESS SBI Read successful.
+**/
+EFI_STATUS
+PchSbiRpPciRead32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ OUT UINT32 *Data32
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT8 Response;
+ UINT16 Fid;
+
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigRead,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR,"Sideband Read Failed\n"));
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ This function And then Or Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[in] Data32And Value of Config register to be And-ed
+ @param[in] Data32AOr Value of Config register to be Or-ed
+
+ @retval EFI_SUCCESS SBI Read and Write successful.
+**/
+EFI_STATUS
+PchSbiRpPciAndThenOr32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ IN UINT32 Data32And,
+ IN UINT32 Data32Or
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT32 Data32;
+ UINT8 Response;
+ UINT16 Fid;
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Status = PchSbiRpPciRead32 (RpIndex, Offset, &Data32);
+ if (Status == EFI_SUCCESS) {
+ Data32 &= Data32And;
+ Data32 |= Data32Or;
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigWrite,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ &Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR,"Sideband Write Failed\n"));
+ ASSERT (FALSE);
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ Check if RST PCIe Storage Remapping is enabled based on policy
+
+ @param[in] RstPcieStorageRemap The PCH PCIe Storage remapping
+
+ @retval TRUE RST PCIe Storage Remapping is enabled
+ @retval FALSE RST PCIe Storage Remapping is disabled
+**/
+BOOLEAN
+IsRstPcieStorageRemapEnabled (
+ IN CONST PCH_RST_PCIE_STORAGE_CONFIG *RstPcieStorageRemap
+ )
+{
+ BOOLEAN RstPcieStorageRemapEnabled;
+ UINTN Index;
+
+ RstPcieStorageRemapEnabled = FALSE;
+
+ DEBUG ((DEBUG_INFO, "IsRstPcieStorageRemapEnabled Started\n"));
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ if (RstPcieStorageRemap[Index].Enable == 1) {
+ RstPcieStorageRemapEnabled = TRUE;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "IsRstPcieStorageRemapEnabled Ended\n"));
+ return RstPcieStorageRemapEnabled;
+}
+
+/**
+ Disable the RST remap address decoding range while RST is disabled.
+
+ @param[in] AhciBar ABAR address
+**/
+VOID
+DisableRstRemapDecoding (
+ UINT32 AhciBar
+ )
+{
+ UINTN PciSataRegBase;
+ UINT32 OrgAhciBar;
+ UINT8 OrgCmd;
+
+ if (AhciBar == 0) {
+ DEBUG ((DEBUG_ERROR, "DisableRstRemapDecoding: Invalid AHCI BAR address.\n"));
+ ASSERT (FALSE);
+ return;
+ }
+
+ PciSataRegBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA);
+ OrgCmd = MmioRead8 (PciSataRegBase + PCI_COMMAND_OFFSET);
+ OrgAhciBar = MmioRead32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR);
+
+ if (AhciBar != OrgAhciBar) {
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, 0);
+ MmioWrite32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR, AhciBar);
+ }
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // Program "NVM Remap Memory BAR Enable", AHCIBar offset A4h [0] to ['0b']
+ // Also set NRMO AHCIBar offset A4h [27:16] to 0x00F, and MSL AHCIBar offset A4h [12:1] to 0.
+ //
+ DEBUG ((DEBUG_INFO, "DisableRstRemapDecoding: Program AHCIBar offset A4h [27:16, 12:1, 0] to [0x00F, 0, 0] to disable remap decoding\n"));
+ MmioWrite32 (AhciBar + R_PCH_SATA_VS_CAP, (0x00F << N_PCH_SATA_VS_CAP_NRMO));
+
+ if (AhciBar != OrgAhciBar) {
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, 0);
+ MmioWrite32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR, OrgAhciBar);
+ }
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, OrgCmd);
+}
+
+/**
+ This function lock down the P2sb SBI before going into OS.
+
+ @param[in] SbiUnlock
+**/
+VOID
+ConfigureP2sbSbiLock (
+ IN CONST BOOLEAN SbiUnlock
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+
+ if (SbiUnlock == FALSE) {
+ P2sbBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB);
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+
+ ///
+ /// Set P2SB PCI Offset 0xE0[31] to 1 to lock down SBI interface.
+ /// @note: SbiLock is write once. Please make sure it's not touched earlier.
+ ///
+ MmioOr8 (P2sbBase + R_PCH_P2SB_E0 + 3, BIT7);
+
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+ }
+}
+
+/**
+ Bios will remove the host accessing right to Sideband register range
+ prior to any 3rd party code execution.
+
+ 1) Set EPMASK5 Offset C4 (bits 29, 28, 27, 26, 17, 16 (PCH-LP only), 10, 1) to disable Sideband access for PSF and MIPI controller
+ 2) Set EPMASK7 Offset CC (bits 6, 5) to disable Sideband access for XHCI controller
+ 3) Set the "Endpoint Mask Lock!", P2SB PCI offset E2h bit[1] to 1.
+
+**/
+VOID
+RemoveSidebandAccess (
+ VOID
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+
+ P2sbBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB);
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+
+ //
+ // Set EPMASK for ports B1, B0, AA, A1 (bits 17, 16 (PCH-LP only), 10, 1) to disable Sideband access for MIPI controller
+ // Set EPMASK for ports BD, BC, BB, BA (bits 29, 28, 27, 26) to disable Sideband access for PCI Root Bridge
+ //
+ if (GetPchSeries () == PchLp) {
+ MmioOr32 (P2sbBase + R_PCH_P2SB_EPMASK5, BIT29 | BIT28 | BIT27 | BIT26 | BIT17 | BIT16 | BIT10 | BIT1);
+ } else {
+ MmioOr32 (P2sbBase + R_PCH_P2SB_EPMASK5, BIT29 | BIT28 | BIT27 | BIT26 | BIT17 | BIT10 | BIT1);
+ }
+
+ //
+ // Set EPMASK for ports E6, E5 (bits 6, 5) to disable Sideband access for XHCI controller
+ //
+ MmioOr32(P2sbBase + R_PCH_P2SB_EPMASK7, BIT6 | BIT5);
+
+ DEBUG((DEBUG_INFO, "Lock the EPMASK registers\n"));
+
+ MmioOr8 (P2sbBase + R_PCH_P2SB_E0 + 2, BIT1);
+
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+}
+
+/**
+ Configure PMC static function disable lock
+**/
+VOID
+ConfigurePmcStaticFunctionDisableLock (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ MmioOr32 (PchPwrmBase + R_PCH_PWRM_ST_PG_FDIS_PMC_1, B_PCH_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK);
+}
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+PrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ )
+{
+ UINT32 Offset;
+ DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
+ for (Offset = 0; Offset < PrintSize; Offset++) {
+ if ((Offset % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02X ", MmioRead8 (PrintMmioBase + Offset)));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+VOID
+PrintPchPciConfigSpace (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 00 - 0 ] Host Bridge\n"));
+ PrintRegisters (MmPciBase ( 0,0,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 01 - 0 ] PCI Bridge (0-1) x16@1 (x16)\n"));
+ PrintRegisters (MmPciBase ( 0,1,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 02 - 0 ] IGD\n"));
+ PrintRegisters (MmPciBase ( 0,2,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 03 - 0 ] High Def Audio\n"));
+ PrintRegisters (MmPciBase (00, 03, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 20(0x14) - 0 ] XHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 20, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 0 ] ME\n"));
+ PrintRegisters (MmPciBase (00, 22, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 2 ] ME IDER\n"));
+ PrintRegisters (MmPciBase (00, 22, 02), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 3 ] ME SOL\n"));
+ PrintRegisters (MmPciBase (00, 22, 03), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 25(0x19) - 0 ] LAN\n"));
+ PrintRegisters (MmPciBase (00, 25, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 26(0x1A) - 0 ] EHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 26, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 27(0x1B) - 0 ] High Def Audio\n"));
+ PrintRegisters (MmPciBase (00, 27, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 28(0x1C) - 0 ] PCI Bridge (0-2) x0@1 (x1)\n"));
+ PrintRegisters (MmPciBase (00, 28, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: AECH\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0100, 0x040,0x0100);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: DFT\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0310, 0x030,0x0310);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: VC0\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0340, 0x020,0x0340);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: Port Configuration Extension\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0400, 0x020,0x0400);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 28(0x1C) - 6 ] PCI Bridge (0-3:10) x0@1 (x1)\n"));
+ PrintRegisters (MmPciBase (00, 28, 06), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 29(0x1D) - 0 ] EHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 29, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 0 ] ISA Bridge\n"));
+ PrintRegisters (MmPciBase (00, 31, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 2 ] SATA\n"));
+ PrintRegisters (MmPciBase (00, 31, 02), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 4 ] SMBus Controller\n"));
+ PrintRegisters (MmPciBase (00, 31, 04), 256, 0);
+
+ DEBUG ((DEBUG_VERBOSE, "\n\n"));
+}
+
+/**
+ Program Xhci Port Disable Override
+
+ @param[in] XhciMmioBase xHCI controller MBAR0 address
+ @param[in] Usb2DisabledPorts Disabled USB2 ports where each port has its disabling bit
+ @param[in] Usb3DisabledPorts Disabled USB3 ports where each port has its disabling bit
+
+ @retval TRUE if platform reset is needed, otherwise FALSE is returned
+**/
+BOOLEAN
+UsbPdoProgramming (
+ IN UINTN XhciMmioBase,
+ IN UINT32 Usb2DisabledPorts,
+ IN UINT32 Usb3DisabledPorts
+ )
+{
+ UINT32 Index;
+ UINT32 XhciUsb2Pdo;
+ UINT32 XhciUsb3Pdo;
+ UINT32 XhciUsb2PdoRd;
+ UINT32 XhciUsb3PdoRd;
+ UINT32 XhciUsb3PortScStartingOffset;
+ UINT32 XhciUsb3PortScOffset;
+ UINT32 XhciPlsTimeout;
+
+ DEBUG ((DEBUG_INFO, "UsbPdoProgramming () start\n"));
+ DEBUG ((DEBUG_INFO, "xHCI: Usb2DisabledPorts = 0x%x\n", Usb2DisabledPorts));
+ DEBUG ((DEBUG_INFO, "xHCI: Usb3DisabledPorts = 0x%x\n", Usb3DisabledPorts));
+
+ //
+ // XHCI PDO for HS
+ //
+ if (GetPchSeries () == PchLp) {
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO) & B_PCH_XHCI_LP_USB2PDO_MASK;
+ } else {
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO) & B_PCH_XHCI_H_USB2PDO_MASK;
+ }
+ XhciUsb2Pdo |= Usb2DisabledPorts;
+
+ //
+ // XHCI PDO for SS
+ //
+ if (GetPchSeries () == PchLp) {
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO) & B_PCH_XHCI_LP_USB3PDO_MASK;
+ XhciUsb3PortScStartingOffset = R_PCH_LP_XHCI_PORTSC01USB3;
+ } else {
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO) & B_PCH_XHCI_H_USB3PDO_MASK;
+ XhciUsb3PortScStartingOffset = R_PCH_H_XHCI_PORTSC01USB3;
+ }
+
+ for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) {
+ // Check if port should be disabled
+ if ((Usb3DisabledPorts & (BIT0 << Index)) != 0) {
+ // Check if PDO bit has not been set yet
+ if (((XhciUsb3Pdo & (UINT32)(BIT0 << Index)) == 0)) {
+ // Calculate port PortSC register offset in xHCI MMIO space
+ XhciUsb3PortScOffset = (XhciUsb3PortScStartingOffset + (Index * 0x10));
+
+ // Disable port before setting PDO bit for it
+ MmioOr32 (XhciMmioBase + XhciUsb3PortScOffset, B_PCH_XHCI_PORTSCXUSB3_PED);
+
+ // Poll for PLS (PortSC[5:8]) to reach 0x4 before setting PDO for the port
+ for (XhciPlsTimeout = 0; XhciPlsTimeout < PORT_PLS_TIMEOUT; XhciPlsTimeout++) {
+ if ((MmioRead32 (XhciMmioBase + XhciUsb3PortScOffset) & B_PCH_XHCI_PORTSCXUSB3_PLS) == V_PCH_XHCI_PORTSCXUSB3_PLS_DISABLED) {
+ break;
+ }
+ MicroSecondDelay (10);
+ }
+
+ if (XhciPlsTimeout == PORT_PLS_TIMEOUT) {
+ DEBUG ((DEBUG_ERROR, "[xHCI PDO] PLS Polling for Disabled has timed out for port %d\n", Index + 1));
+ }
+
+ // A '1' in a bit position prevents the corresponding USB3 port from reporting a Device Connection to the XHC
+ XhciUsb3Pdo |= (UINT32) (B_PCH_XHCI_USB3PDO_DIS_PORT0 << Index);
+
+ // Put port back to RxDetect state
+ // Need to write LWS and PLS regs with same MMIO operation otherwise PLS write will be ignored
+ MmioOr32 (XhciMmioBase + XhciUsb3PortScOffset, (B_PCH_XHCI_PORTSCXUSB3_LWS | V_PCH_XHCI_PORTSCXUSB3_PLS_RXDETECT));
+ }
+ }
+ }
+
+ //
+ // USB2PDO and USB3PDO are Write-Once registers and bits in them are in the SUS Well.
+ //
+ MmioWrite32 (XhciMmioBase + R_PCH_XHCI_USB2PDO, XhciUsb2Pdo);
+ MmioWrite32 (XhciMmioBase + R_PCH_XHCI_USB3PDO, XhciUsb3Pdo);
+
+ XhciUsb2PdoRd = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO);
+ XhciUsb3PdoRd = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO);
+
+ //
+ // If USB2PDO and USB3PDO are not updated successfully perform Warm Reset to unlock RWO bits.
+ //
+ if ((XhciUsb2Pdo != XhciUsb2PdoRd) || (XhciUsb3Pdo != XhciUsb3PdoRd)) {
+ DEBUG ((DEBUG_ERROR, "UsbPdoProgramming: PDO register locked. Performing Warm Reset\n"));
+ return TRUE;
+ }
+
+ DEBUG ((DEBUG_INFO, "UsbPdoProgramming () end\n"));
+ return FALSE;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c
new file mode 100644
index 0000000000..77dd285430
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c
@@ -0,0 +1,127 @@
+/** @file
+ This file contains functions that configures PCI Express Root Ports function swapping.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchInitCommonLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/S3BootScriptLib.h>
+
+/**
+ Configure root port function number mapping
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+PchConfigureRpfnMapping (
+ VOID
+ )
+{
+ UINT8 PortIndex;
+ UINT8 OriginalFuncZeroRp;
+ UINT8 MaxPciePortNum;
+ UINT32 Data32;
+ UINTN DevNum;
+ UINTN FuncNum;
+ UINTN RpBase;
+ UINT32 ControllerPcd[PCH_MAX_PCIE_CONTROLLERS];
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+ UINT32 PcieControllers;
+ UINT32 ControllerIndex;
+ UINT32 FirstController;
+ PCH_SBI_PID ControllerPid;
+
+ DEBUG ((DEBUG_INFO,"PchConfigureRpfnMapping () Start\n"));
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ PcieControllers = GetPchMaxPcieControllerNum ();
+
+ for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
+ PchPcrRead32 (PchGetPcieControllerSbiPid (ControllerIndex), R_PCH_PCR_SPX_PCD, &ControllerPcd[ControllerIndex]);
+ }
+
+ ///
+ /// Configure root port function number mapping
+ ///
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; ) {
+ GetPchPcieRpDevFun (PortIndex, &DevNum, &FuncNum);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) DevNum, (UINT32) FuncNum);
+ //
+ // Search for first enabled function
+ //
+ if (MmioRead16 (RpBase) != 0xFFFF) {
+ if (FuncNum != 0) {
+ //
+ // First enabled root port that is not function zero will be swapped with function zero on the same device
+ // RP PCD register must sync with PSF RP function config register
+ //
+ ControllerIndex = PortIndex / 4;
+ OriginalFuncZeroRp = (PortIndex / 8) * 8;
+ FirstController = OriginalFuncZeroRp / 4;
+
+ //
+ // The enabled root port becomes function zero
+ //
+ ControllerPcd[ControllerIndex] &= (UINT32) ~(B_PCH_PCR_SPX_PCD_RP1FN << ((PortIndex % 4) * S_PCH_PCR_SPX_PCD_RP_FIELD));
+ ControllerPcd[ControllerIndex] |= 0u;
+ //
+ // Origianl function zero on the same device takes the numer of the current port
+ //
+ ControllerPcd[FirstController] &= (UINT32) ~B_PCH_PCR_SPX_PCD_RP1FN;
+ ControllerPcd[FirstController] |= (UINT32) FuncNum;
+
+ //
+ // Program PSF1 RP function config register.
+ //
+ PsfSetPcieFunctionWithS3BootScript (OriginalFuncZeroRp, (UINT32) FuncNum);
+ PsfSetPcieFunctionWithS3BootScript (PortIndex, 0);
+ }
+ //
+ // Once enabled root port was found move to next PCI device
+ //
+ PortIndex = ((PortIndex / 8) + 1) * 8;
+ continue;
+ }
+ //
+ // Continue search for first enabled root port
+ //
+ PortIndex++;
+ }
+
+ //
+ // Write to PCD and lock the register
+ //
+ for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
+ ControllerPid = PchGetPcieControllerSbiPid (ControllerIndex);
+ Data32 = ControllerPcd[ControllerIndex] | B_PCH_PCR_SPX_PCD_SRL;
+ PchPcrWrite32 (ControllerPid, R_PCH_PCR_SPX_PCD, Data32);
+ PCH_PCR_BOOT_SCRIPT_WRITE (
+ S3BootScriptWidthUint32,
+ ControllerPid, R_PCH_PCR_SPX_PCD,
+ 1,
+ &Data32
+ );
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
new file mode 100644
index 0000000000..df4900d964
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Component description file for the PchInitCommonLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiDxeSmmPchInitCommonLib
+ FILE_GUID = E9C4FE04-8A79-43FA-B3E0-603359C31B43
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchInitCommonLib
+
+[Sources]
+ PchInitCommon.c
+ PchRpfn.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
+ PchPcieRpLib
+ PchP2sbLib
+ PchSbiAccessLib
+ PchInfoLib
+ PchPsfPrivateLib
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
new file mode 100644
index 0000000000..815b800db7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
@@ -0,0 +1,1933 @@
+/** @file
+ This file contains routines that support PCI Express initialization
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchPciExpressHelpersLibrary.h"
+
+const UINT8 mPcieL1sTposMultiplier[] = {2, 10, 100};
+
+/*
+ Returns Tpower_on capability of device
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+*/
+T_POWER_ON GetTpoCapability (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ )
+{
+ T_POWER_ON Tpo;
+ UINT32 L1ssCapabilities;
+
+ L1ssCapabilities = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ Tpo.Scale = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTPOS) >> N_PCIE_EX_L1SCAP_PTPOS;
+ Tpo.Value = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTV) >> N_PCIE_EX_L1SCAP_PTV;
+ return Tpo;
+}
+
+/*
+ Returns Tpower_on currently programed in a device
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+*/
+T_POWER_ON GetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ )
+{
+ T_POWER_ON Tpo;
+ UINT32 L1ssControl2;
+
+ L1ssControl2 = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL2_OFFSET);
+ Tpo.Scale = L1ssControl2 & 0x3;
+ Tpo.Value = (L1ssControl2 & 0xF8) >> N_PCIE_EX_L1SCTL2_POWT;
+ return Tpo;
+}
+
+/*
+ Sets Tpower_on in a device
+ According to spec, Tpower_on can only be updated while L1.2 is disabled
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+ @param[in] Tpo value to be programmed into Tpower_on
+*/
+VOID SetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset,
+ T_POWER_ON Tpo
+ )
+{
+ UINT32 L1_2;
+
+ L1_2 = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET) & (BIT2 | BIT0);
+ MmioAnd32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, (UINT32)(~ (BIT2 | BIT0)));
+ MmioAndThenOr32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, (UINT32)(~0xFB), (Tpo.Value << 3) + Tpo.Scale);
+ MmioOr32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, L1_2);
+}
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+*/
+UINT32 TpoToUs (
+ T_POWER_ON Tpo
+ )
+{
+ static const UINT8 TpoScaleMultiplier[] = {2, 10, 100};
+
+ ASSERT (Tpo.Scale < TpoScaleMax);
+ if (Tpo.Scale >= TpoScaleMax) {
+ return 0;
+ }
+ return (TpoScaleMultiplier[Tpo.Scale] * Tpo.Value);
+}
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+{
+ UINT8 CapHeaderOffset;
+ UINT8 CapHeaderId;
+ UINTN DeviceBase;
+
+ DeviceBase = MmPciBase (Bus, Device, Function);
+
+ DEBUG ((DEBUG_INFO,"PcieFindCapId () BDF %0x: %0x :%0x, CapId = %0x \n", Bus, Device, Function, CapId));
+ if ((MmioRead8 (DeviceBase + PCI_PRIMARY_STATUS_OFFSET) & EFI_PCI_STATUS_CAPABILITY) == 0x00) {
+ ///
+ /// Function has no capability pointer
+ ///
+ return 0;
+ } else {
+ ///
+ /// Check the header layout to determine the Offset of Capabilities Pointer Register
+ ///
+ if ((MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) {
+ ///
+ /// If CardBus bridge, start at Offset 0x14
+ ///
+ CapHeaderOffset = EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR;
+ } else {
+ ///
+ /// Otherwise, start at Offset 0x34
+ ///
+ CapHeaderOffset = PCI_CAPBILITY_POINTER_OFFSET;
+ }
+ ///
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1));
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) {
+ CapHeaderId = MmioRead8 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ if (CapHeaderOffset > PCI_MAXLAT_OFFSET) {
+ ///
+ /// Return valid capability offset
+ ///
+ return CapHeaderOffset;
+ } else {
+ ASSERT ((FALSE));
+ return 0;
+ }
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers (including the initial pointer at 34h) are reserved
+ /// and must be implemented as 00b although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset + 1) & ((UINT8) ~(BIT0 | BIT1));
+ }
+ return 0;
+ }
+}
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Reporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+{
+ UINT16 CapHeaderOffset;
+ UINT16 CapHeaderId;
+ UINTN DeviceBase;
+
+ DeviceBase = MmPciBase (Bus, Device, Function);
+
+ ///
+ /// Start to search at Offset 0x100
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = R_PCH_PCIE_EXCAP_OFFSET;
+ while (CapHeaderOffset != 0 && CapHeaderId != MAX_UINT16) {
+ CapHeaderId = MmioRead16 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ return CapHeaderOffset;
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers are reserved and must be implemented as 00b
+ /// although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = (MmioRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(BIT0 | BIT1));
+ }
+
+ return 0;
+}
+
+/**
+ This returns ClkReq Number from Port Number
+
+ @param[in] PortIndex PCIe Port Number (Zero Base)
+
+ @retval ClkReq Number
+**/
+UINT8
+GetPortClkReqNumber (
+ IN UINT8 PortIndex
+ )
+{
+ UINT8 ClkReqNum;
+ PchPcrRead8 (PID_FIA, R_PCH_PCR_FIA_DRCRM1 + (PortIndex / 2), &ClkReqNum);
+ if (PortIndex % 2 == 0) {
+ ClkReqNum &= 0x0F;
+ } else {
+ ClkReqNum = ClkReqNum >> 4;
+ }
+ return ClkReqNum;
+}
+
+/**
+ Set Common clock to Root port and Endpoint PCI device
+
+ @param[in] Bus1 Root port Pci Bus Number
+ @param[in] Device1 Root port Pci Device Number
+ @param[in] Function1 Root port Pci Function Number
+ @param[in] Bus2 Endpoint Pci Bus Number
+ @param[in] Device2 Endpoint Pci Device Number
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS VC mapping correctly initialized
+**/
+EFI_STATUS
+PcieSetCommonClock (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2
+ )
+{
+ UINT8 CapOffset1;
+ UINT8 CapOffset2;
+ BOOLEAN CommonClockSupport;
+ UINTN DeviceBase1;
+ UINTN DeviceBase2;
+ UINT16 RegData16;
+ UINT8 FunctionIndex;
+ UINT8 Function2;
+
+ DeviceBase1 = MmPciBase (Bus1, Device1, Function1);
+
+ ///
+ /// Get the pointer to the Port PCI Express Capability Structure.
+ ///
+ CommonClockSupport = FALSE;
+ CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset1 == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Check the Port Slot Clock Configuration Bit.
+ ///
+ if ((MmioRead16 (DeviceBase1 + CapOffset1 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DeviceBase2 = MmPciBase (Bus2, Device2, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase2 + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ Function2 = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ Function2 = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= Function2; FunctionIndex++) {
+ DeviceBase2 = MmPciBase (Bus2, Device2, FunctionIndex);
+ ///
+ /// Check the Endpoint Slot Clock Configuration Bit.
+ ///
+ CapOffset2 = PcieFindCapId (Bus2, Device2, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if ((CapOffset2 != 0) && ((MmioRead16 (DeviceBase2 + CapOffset2 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC) != 0)) {
+ ///
+ /// Common clock is supported, set common clock bit on root port
+ /// and the endpoint
+ ///
+ if (CommonClockSupport == FALSE) {
+ MmioOr8 (DeviceBase1 + CapOffset1 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+ CommonClockSupport = TRUE;
+ }
+ MmioOr8 (DeviceBase2 + CapOffset2 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+ }
+ }
+ ///
+ /// If common clock not supported on root port and endpoint, return EFI_UNSUPPORTED
+ ///
+ if (CommonClockSupport == FALSE) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Retrain the Link per PCI Express Specification.
+ ///
+ MmioOr8 (DeviceBase1 + CapOffset1 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_RL);
+
+ ///
+ /// Wait until Re-Training has completed.
+ ///
+ do {
+ RegData16 = MmioRead16 (DeviceBase1 + CapOffset1 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_LT;
+ } while (RegData16 != 0);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] RootDevice Rootport Device Number
+ @param[in] RootFunction Rootport Function Number
+
+ @retval None
+**/
+VOID
+PcieSetClkreq (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction
+ )
+{
+ UINT8 CapOffset;
+ UINTN DeviceBase;
+ UINT8 FunctionIndex;
+ UINT8 Function;
+ BOOLEAN ClkreqPerPortSupported;
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ClkreqPerPortSupported = TRUE;
+
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ Function = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ Function = 0;
+ }
+ ///
+ /// Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if
+ /// exists then enable the CLKREQ# bit (BIT8) on that function
+ ///
+ for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) {
+ ///
+ /// Find the PCIe Cap Id (10h)
+ ///
+ CapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ ///
+ /// Check if CLKREQ# is supported by the endpoints
+ ///
+ if ((MmioRead32 (DeviceBase + CapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM) == 0) {
+ ///
+ /// CLKREQ# is not supported so dont do anything
+ ///
+ ClkreqPerPortSupported = FALSE;
+ break;
+ }
+ }
+
+ if (ClkreqPerPortSupported == FALSE) {
+ return;
+ }
+ ///
+ /// Now enable the CLKREQ#
+ ///
+ for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) {
+ ///
+ /// Find the PCIe Cap Id (10h)
+ ///
+ CapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ MmioOr16 (DeviceBase + CapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_ECPM);
+ }
+}
+/**
+ This function get or set the Max Payload Size on all the end point functions
+
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+ @param[in, out] MaxPayload The Max Payolad Size of the root port
+ @param[in] Operation True: Set the Max Payload Size on all the end point functions
+ False: Get the Max Payload Size on all the end point functions
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieMaxPayloadSize (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN Operation
+ )
+{
+ UINTN DeviceBase;
+ UINT8 PcieCapOffset;
+ UINT16 EndPointMaxPayload;
+ UINT8 FunctionIndex;
+ UINT8 EndPointFunction;
+
+ ///
+ /// Obtain the Max Payload Size for all the end point functions
+ ///
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ if (MmioRead16 (DeviceBase + PCI_VENDOR_ID_OFFSET) != MAX_UINT16) {
+ ///
+ /// Get the pointer to the Endpoint PCI Express Capability Structure.
+ ///
+ PcieCapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (PcieCapOffset == 0) {
+ continue;
+ }
+
+ if (Operation == TRUE) {
+ ///
+ /// Set the Max Payload Size of the end point function
+ ///
+ MmioAndThenOr16 (
+ DeviceBase + PcieCapOffset + R_PCIE_DCTL_OFFSET,
+ (UINT16) ~(B_PCIE_DCTL_MPS),
+ *MaxPayload << N_PCIE_DCTL_MPS
+ );
+ } else {
+ ///
+ /// Get the end point function Max Payload Size support
+ ///
+ EndPointMaxPayload = MmioRead16 (DeviceBase + PcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS;
+ ///
+ /// Obtain the minimum Max Payload Size between the PCIE root Port and the end point functions
+ ///
+ if (*MaxPayload > EndPointMaxPayload) {
+ *MaxPayload = EndPointMaxPayload;
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function disable the forwarding of EOI messages unless it discovers
+ an IOAPIC behind this root port.
+
+ @param[in] RootBus The Bus Number of the root port
+ @param[in] RootDevice The Device Number of the root port
+ @param[in] RootFunction The Function Number of the root port
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieSetEoiFwdDisable (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice
+ )
+{
+ BOOLEAN IoApicBehind;
+ UINTN RootDeviceBase;
+ UINTN DeviceBase;
+ UINT8 ProgInterface;
+ UINT8 SubClassCode;
+ UINT8 BaseClassCode;
+ UINT8 FunctionIndex;
+ UINT8 EndPointFunction;
+ UINTN RootPortIndex;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ IoApicBehind = FALSE;
+ RootDeviceBase = MmPciBase (RootBus, RootDevice, RootFunction);
+
+ ///
+ /// Check if an IOAPIC behind the root port
+ ///
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ BaseClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 2);
+ SubClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 1);
+ ProgInterface = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET);
+ if ((BaseClassCode == PCI_CLASS_SYSTEM_PERIPHERAL) &&
+ (SubClassCode == PCI_SUBCLASS_PIC) &&
+ ((ProgInterface == PCI_IF_APIC_CONTROLLER) ||
+ (ProgInterface == PCI_IF_APIC_CONTROLLER2))) {
+ IoApicBehind = TRUE;
+ }
+ }
+ ///
+ /// PCH BIOS Spec Section 8.15 Additional PCI Express* Programming Steps
+ /// Step 27
+ /// If there is no IOAPIC behind the root port, set EOI Forwarding Disable bit (PCIE RP PCI offset D4h[1]) to 1b.
+ ///
+ if (IoApicBehind == FALSE) {
+ MmioOr32 (RootDeviceBase + R_PCH_PCIE_MPC2, B_PCH_PCIE_MPC2_EOIFD);
+ } else {
+ ///
+ /// If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ /// accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ ///
+ ///
+ Status = GetPchPcieRpNumber ((UINTN) RootDevice, (UINTN) RootFunction, &RootPortIndex);
+ ASSERT_EFI_ERROR (Status);
+
+ PsfConfigurEoiForPciePort ((UINT32)RootPortIndex);
+ }
+
+ return Status;
+}
+
+typedef enum {
+ CalculateAspm,
+ ManualAspm,
+ SetAspm
+} OPERATION;
+
+/**
+ This function compares the actual latency in LatencyValue1
+ with actual latency in LatencyValue2 and stores the minimum
+ back to LatencyValue1, in the required format.
+ If this is the first call, then LatencyValue1 will be replaced by LatencyValue2.
+
+ @param[in, out] LatencyValue1 - Current latency value
+ @param[in] LatencyValue2 - Latency value from the Table
+
+ @retval None
+**/
+VOID
+DetermineLatencyValue (
+ IN OUT UINT16 *LatencyValue1,
+ IN UINT16 LatencyValue2
+ )
+{
+ ASSERT (LTR_SCALE_VALUE (*LatencyValue1) < 6);
+ ASSERT (LTR_SCALE_VALUE (LatencyValue2) < 6);
+ ///
+ /// If there are more than one device behind a bridge that are part of the override table,
+ /// store the lower latency value and corresponding scale bits back to LatencyValue1
+ ///
+ if ((LTR_LATENCY_NS (*LatencyValue1) == 0) || (LTR_LATENCY_NS (*LatencyValue1) > LTR_LATENCY_NS (LatencyValue2))) {
+ *LatencyValue1 = LatencyValue2;
+ }
+}
+
+/**
+ This function checks exit latency of L1 and L0s and disables the ASPM state if it is longer than
+ the acceptable latency
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] EndPointPcieCapOffset The pointer to the End Point PCI Express Capability Structure
+ @param[in] RootDeviceBase The Root Port PCI Express Base address
+ @param[in] RootPcieCapOffset The pointer to the Root Port PCI Express Capability Structure
+ @param[in, out] EndPointAspm End Point ASPM setting
+
+ @retval none
+**/
+VOID
+AspmCheckExitLatency (
+ IN UINTN EndPointBase,
+ IN UINT8 EndPointPcieCapOffset,
+ IN UINTN RootDeviceBase,
+ IN UINT32 RootPcieCapOffset,
+ IN OUT UINT16* EndPointAspm
+ )
+{
+
+ UINT32 PortLxLat;
+ UINT32 EndPointLxLat;
+ UINT32 LxLat;
+
+ ///
+ /// Check if L1 should be enabled based on port and endpoint L1 exit latency.
+ ///
+ if ((*EndPointAspm) & BIT1) {
+ PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL1;
+ EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL1;
+
+ LxLat = PortLxLat;
+ if (PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+ ///
+ /// check if the value is bigger than endpoint L1 acceptable exit latency, if it is
+ /// larger than accepted value, then we should disable L1
+ ///
+ LxLat >>= N_PCIE_LCAP_EL1;
+ if (LxLat > ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_E1AL) >> N_PCIE_DCAP_E1AL)) {
+ (*EndPointAspm) &= ~BIT1;
+ }
+ }
+ ///
+ /// Check if L0s should be enabled based on port and endpoint L0s exit latency.
+ ///
+ if ((*EndPointAspm) & BIT0) {
+ PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL0;
+ EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL0;
+
+ LxLat = PortLxLat;
+ if (PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+ ///
+ /// check if the value is bigger than endpoint L0s acceptable exit latency, if it is
+ /// larger than accepted value, then we should disable L0s
+ ///
+ LxLat >>= N_PCIE_LCAP_EL0;
+ if (LxLat > ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_E0AL) >> N_PCIE_DCAP_E0AL)) {
+ (*EndPointAspm) &= ~BIT0;
+ }
+ }
+ return;
+}
+/**
+ This function gets override Aspm values if the end point is found in the override look up table
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[in, out] EndPointAspm End Point ASPM setting
+
+ @retval none
+**/
+
+VOID
+GetOverrideAspm (
+ IN UINTN EndPointBase,
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT16 *EndPointAspm
+ )
+{
+ UINT8 EndPointBaseClassCode;
+ UINT8 EndPointSubClassCode;
+ UINT8 PcieDeviceIndex;
+ ///
+ /// Mask APMC with values from lookup table.
+ /// RevID of 0xFF applies to all steppings.
+ ///
+ EndPointBaseClassCode = MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET);
+ EndPointSubClassCode = MmioRead8 (EndPointBase + R_PCI_SCC_OFFSET);
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1L2Override) == PchPcieL1L2Override) &&
+ ((DevAspmOverride[PcieDeviceIndex].VendorId == EndPointVendorId) ||
+ (DevAspmOverride[PcieDeviceIndex].VendorId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) ||
+ (DevAspmOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].RevId == EndPointRevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].BaseClassCode == EndPointBaseClassCode) ||
+ (DevAspmOverride[PcieDeviceIndex].BaseClassCode == 0xFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].SubClassCode == EndPointSubClassCode) ||
+ (DevAspmOverride[PcieDeviceIndex].SubClassCode == 0xFF))) {
+ ///
+ /// Override value of 0xFF applies to all.
+ ///
+ *EndPointAspm = DevAspmOverride[PcieDeviceIndex].EndPointAspm;
+ break;
+ }
+ }
+}
+
+/**
+ This function gets override L1 Substate Capability offset pointer
+ if the end point is found in the override look up table
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[out] EndPointL1SubStateCapOffset Pointer to L1 Substate Capability Structure
+ @param[out] EndPointL1SubStateCapMask L1 Substate Capability Mask
+ @param[out] EndPointL1sCommonModeRestoreTime L1 Substate Port Common Mode Restore Time
+ @param[out] EndPointL1sTpowerOnScale L1 Substate Port Tpower_on Scale
+ @param[out] EndPointL1sTpowerOnValue L1 Substate Port Tpower_on Value
+
+ @retval none
+**/
+
+VOID
+GetOverrideL1sCapOffsetAndValue (
+ IN UINTN EndPointBase,
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ OUT UINT16 *EndPointL1SubStateCapOffset,
+ OUT UINT8 *EndPointL1SubStateCapMask,
+ OUT UINT8 *EndPointL1sCommonModeRestoreTime,
+ OUT UINT8 *EndPointL1sTpowerOnScale,
+ OUT UINT8 *EndPointL1sTpowerOnValue
+ )
+{
+ UINT8 PcieDeviceIndex;
+ ///
+ /// Get the endpoint supports L1 Substates Capabilities from Override Table
+ ///
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) &&
+ (EndPointVendorId == DevAspmOverride[PcieDeviceIndex].VendorId) &&
+ (EndPointDeviceId == DevAspmOverride[PcieDeviceIndex].DeviceId) &&
+ ((EndPointRevId == DevAspmOverride[PcieDeviceIndex].RevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) {
+ if ((EndPointVendorId == V_PCH_INTEL_VENDOR_ID) &&
+ ((EndPointDeviceId == 0x08B1) || (EndPointDeviceId == 0x08B2) ||
+ (EndPointDeviceId == 0x08B3) || (EndPointDeviceId == 0x08B4))
+ && ((MmioRead32 (EndPointBase + DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset) & 0xFFFF) != 0xCAFE)) {
+ continue;
+ }
+ *EndPointL1SubStateCapOffset = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset;
+ *EndPointL1SubStateCapMask = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapMask & 0x0F;
+ *EndPointL1sCommonModeRestoreTime = DevAspmOverride[PcieDeviceIndex].L1sCommonModeRestoreTime & 0xFF;
+ *EndPointL1sTpowerOnScale = DevAspmOverride[PcieDeviceIndex].L1sTpowerOnScale & 0x03;
+ *EndPointL1sTpowerOnValue = DevAspmOverride[PcieDeviceIndex].L1sTpowerOnValue & 0x1F;
+
+ break;
+ }
+ }
+}
+
+/**
+ This function configures the L1 Substates.
+ It can be used for Rootport and endpoint devices.
+
+ @param[in] DownstreamPort Indicates if the device about to be programmed is a downstream port
+ @param[in] DeviceBase Device PCI configuration base address
+ @param[in] L1SubstateExtCapOffset Pointer to L1 Substate Capability Structure
+ @param[in] PortL1SubstateCapSupport L1 Substate capability setting
+ @param[in] PortCommonModeRestoreTime Common Mode Restore Time
+ @param[in] PortTpowerOnValue Tpower_on Power On Wait Time
+ @param[in] PortTpowerOnScale Tpower-on Scale
+
+ @retval none
+**/
+VOID
+ConfigureL1s (
+ IN BOOLEAN DownstreamPort,
+ IN UINTN DeviceBase,
+ IN UINT16 L1SubstateExtCapOffset,
+ IN UINT32 PortL1SubstateCapSupport,
+ IN UINT32 PortCommonModeRestoreTime,
+ IN UINT32 PortTpowerOnValue,
+ IN UINT32 PortTpowerOnScale
+ )
+{
+ //
+ // For downstream port only:
+ // Program Common Mode Restore Time, but disable L1.2 first
+ //
+ if (DownstreamPort) {
+ MmioAnd32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(BIT2 | BIT0)
+ );
+
+ ///
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and Set the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on both
+ /// Pcie root port and device.
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xFF00),
+ (UINT32) PortCommonModeRestoreTime << 8
+ );
+ }
+
+ ///
+ /// PCH BIOS Spec Section 8.3 ASPM on DMI and the PCI Express* Root Ports
+ /// Step 6
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[3:0], and set the smallest common subset supported
+ /// by both PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[3:0]
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(BIT3 | BIT2 | BIT1 | BIT0),
+ PortL1SubstateCapSupport
+ );
+ ///
+ /// c. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and Set the highest value
+ /// advertised between PCIe root port and device to L1 Sub-States Extended Capability Offset + 0x0C [7:0] on
+ /// both Pcie root port and device.
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL2_OFFSET,
+ 0xFFFFFF04,
+ (UINT32) ((PortTpowerOnValue << N_PCIE_EX_L1SCTL2_POWT) | PortTpowerOnScale)
+ );
+ ///
+ /// d. Set L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// e. Set L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ ///
+
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xE3FF0000),
+ (UINT32) (BIT30 | BIT23 | BIT21)
+ );
+}
+
+/**
+ This function gets the Latency Tolerance Reporting settings from override table
+ if the end point is found in the override look up table
+
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[in, out] LtrOverrideVal Snoop and Non Snoop Latency Values
+ @param[out] ForceLtrOverride This endpoint needs LTR to be permanently overridden
+
+ @retval none
+**/
+VOID
+GetLtrOverride (
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT32* LtrOverrideVal,
+ OUT UINT8* ForceLtrOverride
+ )
+{
+ UINT8 PcieDeviceIndex;
+ UINT16 Data16;
+ UINT32 Data32;
+ ///
+ /// For each device detected, scan the LTR override table
+ /// If there are endpoints connected directly to the rootport then
+ /// LtrOverrideVal will be replaced by the value from the table for that endpoint
+ /// If there are endpoints that are behind a bridge and that are also part of the table then
+ /// LtrOverrideVal will maintain the minimum of all such values.
+ /// A non zero value of LtrOverrideVal will indicate:
+ /// i):That there is atleast one entry in the LTR override Table
+ /// ii):The final value to be programmed in offset 0x400. This value will be applied for all the devices
+ /// connected to this root port
+ ///
+ Data32 = *LtrOverrideVal;
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieLtrOverride) == PchPcieLtrOverride) &&
+ (DevAspmOverride[PcieDeviceIndex].VendorId == EndPointVendorId) &&
+ ((DevAspmOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) ||
+ (DevAspmOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].RevId == EndPointRevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) {
+ ///
+ /// Get the Non-Snoop latency value from the table, compare and store the minimum
+ ///
+ if (DevAspmOverride[PcieDeviceIndex].NonSnoopLatency & BIT15) {
+ Data16 = (UINT16) ((Data32 & 0xFFFF0000) >> 16);
+ DetermineLatencyValue (
+ &Data16,
+ DevAspmOverride[PcieDeviceIndex].NonSnoopLatency);
+ Data32 = (Data32 & 0xFFFF) | ((UINT32) (Data16 << 16));
+ }
+ ///
+ /// Get the Snoop latency value from the table, compare and store the minimum
+ ///
+ if (DevAspmOverride[PcieDeviceIndex].SnoopLatency & BIT15) {
+ Data16 = (UINT16) (Data32 & 0xFFFF);
+ DetermineLatencyValue (
+ &Data16,
+ DevAspmOverride[PcieDeviceIndex].SnoopLatency);
+ Data32 = (Data32 & 0xFFFF0000) | (UINT32) Data16;
+ }
+ *LtrOverrideVal = Data32;
+ //
+ // Get the ForceLtrOverride value from table
+ //
+ if (DevAspmOverride[PcieDeviceIndex].ForceLtrOverride == TRUE) {
+ *ForceLtrOverride = TRUE;
+ }
+ break;
+ }
+ }
+ return;
+}
+
+
+/**
+ This function configures the Latency Tolerance Reporting Settings for endpoint devices
+
+ @param[in] RootPortConfig Rootport PCI Express Configuration
+ @param[in] EndPointBus Endpoint Bus Number
+ @param[in] EndPointDevice Endpoint Device Number
+ @param[in] EndPointFunction Endpoint Function Number
+ @param[in] EndPointBase Endpoint PCI Express Address
+ @param[in] EndPointPcieCapOffset Pointer to Endpoint PCI Express Capability Structure
+ @param[in] DeviceCapabilities2 Endpoint Value of Device Capabilities 2 Register (PciE Cap offset + 0x24)
+ @param[in] PchSeries Pch Series
+ @param[in] LtrOverrideVal Snoop and Non Snoop Latency Values
+
+ @retval none
+**/
+VOID
+ConfigureLtr (
+ IN CONST PCH_PCIE_ROOT_PORT_CONFIG* RootPortConfig,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 EndPointFunction,
+ IN UINTN EndPointBase,
+ IN UINT8 EndPointPcieCapOffset,
+ IN UINT32 DeviceCapabilities2,
+ IN PCH_SERIES PchSeries,
+ IN UINT32* LtrOverrideVal
+ )
+{
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT16 LtrExtendedCapOffset;
+ UINT16 DefaultMaxLatency;
+ DefaultMaxLatency = 0;
+ ///
+ /// PCH BIOS Spec Section 8.15.1 Power Optimizer Configuration
+ /// Step 3
+ /// If Endpoint device supports LTR, Device Capabilities 2 Register Offset 24h [11] = 1b,
+ ///
+ if ((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) && (RootPortConfig->LtrEnable == TRUE)) {
+ ///
+ /// PCH BIOS Spec Section 8.15.1 Power Optimizer Configuration
+ /// Step 3.1
+ /// Program Endpoint LTR Mechanism Enable, Device Control 2 Register Offset 28h [10] = 1b
+ /// when device supports LTR but is not found in override table (table listing correct
+ /// latency requirements for devices that supports LTR and also for devices that do not
+ /// support LTR).
+ ///
+ MmioOr16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCTL2_OFFSET, B_PCIE_DCTL2_LTREN);
+ }
+ ///
+ /// Get the pointer to the Endpoint PCI Express Extended Capability Structure
+ /// and configure the Max Snoop and Max No-Snoop Latency for the endpoint
+ ///
+ LtrExtendedCapOffset = PcieFindExtendedCapId (EndPointBus,
+ EndPointDevice,
+ EndPointFunction,
+ R_PCH_PCIE_LTRECH_CID);
+ if (LtrExtendedCapOffset != 0) {
+ Data32 = *LtrOverrideVal;
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3.2
+ /// If B0:Dxx:Fn + 400h is not programmed with snoop latency override value,
+ /// program endpoint max snoop latency register, Latency Tolerance Reporting (LTR)
+ /// Capability Offset 04h [15:0] = 1003h
+
+ DefaultMaxLatency = RootPortConfig->LtrMaxSnoopLatency;
+ Data16 = (UINT16) (Data32 & 0xFFFF);
+ ///
+ /// Set the max snoop latency to either the default max snoop latency or to the snoop latency override value
+ /// that is being programmed for this root port
+ ///
+ DetermineLatencyValue (&Data16, DefaultMaxLatency);
+ MmioAndThenOr16 (EndPointBase + LtrExtendedCapOffset + R_PCH_PCIE_LTRECH_MSLR_OFFSET,
+ (UINT16) (~0x1FFF),
+ Data16);
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3.3
+ /// If B0:Dxx:Fn + 400h is not programmed with non-snoop latency override value,
+ /// program endpoint max non-snoop Latency Register, Latency Tolerance Reporting (LTR)
+ /// Capability Offset 06h [15:0] = 1003h
+
+ DefaultMaxLatency = RootPortConfig->LtrMaxNoSnoopLatency;
+ Data16 = (UINT16) ((Data32 & 0xFFFF0000) >> 16);
+ DetermineLatencyValue (&Data16, DefaultMaxLatency);
+ MmioAndThenOr16 (
+ EndPointBase + LtrExtendedCapOffset
+ + R_PCH_PCIE_LTRECH_MNSLR_OFFSET,
+ (UINT16) (~0x1FFF),
+ Data16);
+ ///
+ /// Step 4
+ /// If not all devices support LTR
+ /// Program PWRMBASE + 20h = 00010003h
+ /// (Note this register should be saved and restored during S3 transitions)
+ /// Done in PchPcieSmm.c PchPciePmIoTrapSmiCallback ()
+ ///
+ }
+}
+
+/**
+ Calculate/Set EndPoint device Power management settings
+
+ @param[in] RootDeviceBase The Root Port PCI Express address
+ @param[in] RootPcieCapOffset The pointer to the Root Port PCI Express Capability Structure
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in, out] LinkAspmVal Resulting Link ASPM value programmed
+ @param[in] Operation Operation Types
+ @param[in, out] LtrOverrideVal Resulting LTR override value to be programmed
+ @param[in] RootL1SubstateExtCapOffset The register offset of Root Port L1 Substates
+ @param[in, out] L1SubstatesSupported Input and return the result of L1 Substates support
+ @param[in, out] PortL1SubstateCapSupport Input and return Capability of L1 Substate setting
+ @param[in, out] PortCommonModeRestoreTime Input and return common mode restore time of L1 Substate setting
+ @param[in, out] PortTpowerOnValue Input and return power on value of L1 Substate setting
+ @param[in, out] PortTpowerOnScale Input and return power on scale of L1 Substate setting
+ @param[in] RootPortConfig Pcie Power Optimizer Configuration
+ @param[in, out] AspmOverride Input and return the Aspm Override enable for pre-1.1 devices
+ @param[in, out] ClkreqPerPortSupported Input to check if clkreq per port is supportted
+ @param[in, out] RpAndEndPointsLtrSupported Input to check if LTR per port is supportted
+ @param[out] ForceLtrOverride One of endpoints needs LTR to be permanently overridden
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device
+
+ @retval EFI_OUT_OF_RESOURCES The endpoint device is a bridge, but the Subordinate Bus Number of
+ the root port is not greater than its Secondary Bus Number. You may
+ get this error if PCI emulation is not done before this function gets
+ called and the Policy settings of "TempRootPortBusNumMax" and
+ "TempRootPortBusNumMin" do not provide enough resource for temp bus
+ number usage.
+**/
+EFI_STATUS
+PcieEndPointPm (
+ IN UINTN RootDeviceBase,
+ IN UINT32 RootPcieCapOffset,
+ IN UINT8 EndPointBus,
+ IN UINT32 NumOfDevAspmOverride,
+ IN CONST PCH_PCIE_DEVICE_OVERRIDE *DevAspmOverride,
+ IN OUT UINT16 *LinkAspmVal,
+ IN OPERATION Operation,
+ IN OUT UINT32 *LtrOverrideVal,
+ IN UINT16 RootL1SubstateExtCapOffset,
+ IN OUT BOOLEAN *L1SubstatesSupported,
+ IN OUT UINT32 *PortL1SubstateCapSupport,
+ IN OUT UINT32 *PortCommonModeRestoreTime,
+ IN OUT UINT32 *PortTpowerOnValue,
+ IN OUT UINT32 *PortTpowerOnScale,
+ IN CONST PCH_PCIE_ROOT_PORT_CONFIG *RootPortConfig,
+ IN OUT BOOLEAN *AspmOverride,
+ IN BOOLEAN *ClkreqPerPortSupported,
+ IN OUT BOOLEAN *RpAndEndPointsLtrSupported,
+ OUT UINT8 *ForceLtrOverride
+ )
+{
+ EFI_STATUS Status;
+ UINTN EndPointBase;
+ UINT8 EndPointFunction;
+ UINT8 EndPointPcieCapOffset;
+ UINT16 EndPointAspm;
+ UINT16 EndPointVendorId;
+ UINT16 EndPointDeviceId;
+ UINT8 EndPointRevId;
+ UINT8 DownStreamBusMin;
+ UINT8 ClassCode;
+ UINT8 RootDevSubBusNum;
+ BOOLEAN BusAssign;
+ UINT8 DeviceIndex;
+ UINT8 FunctionIndex;
+ UINT32 DeviceCapabilities2;
+ UINT16 EndPointL1SubStateCapOffset;
+ UINT32 EndPointL1Substates;
+ UINT8 EndPointL1sCommonModeRestoreTime;
+ UINT8 EndPointL1sTpowerOnScale;
+ UINT8 EndPointL1sTpowerOnValue;
+ UINT8 EndPointL1SubStateCapMask;
+ PCH_SERIES PchSeries;
+ BOOLEAN DownstreamPort;
+ UINT16 PcieEndCapOffset;
+ UINT16 PcieEndDeviceType;
+
+ PchSeries = GetPchSeries ();
+
+ DEBUG ((DEBUG_INFO, "PcieEndPointPm () Start EndPointBus %0x\n", EndPointBus));
+ for (DeviceIndex = 0; DeviceIndex <= PCI_MAX_DEVICE; DeviceIndex++) {
+ EndPointBase = MmPciBase (EndPointBus, DeviceIndex, 0);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (EndPointBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ EndPointBase = MmPciBase (EndPointBus, DeviceIndex, FunctionIndex);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+
+ //
+ // Get the pointer to the Endpoint PCI Express Capability Structure.
+ //
+ EndPointPcieCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (EndPointPcieCapOffset == 0) {
+ return EFI_NOT_FOUND;
+ }
+ EndPointVendorId = MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET);
+ EndPointDeviceId = MmioRead16 (EndPointBase + PCI_DEVICE_ID_OFFSET);
+ EndPointRevId = MmioRead8 (EndPointBase + PCI_REVISION_ID_OFFSET);
+
+ EndPointL1SubStateCapOffset = 0;
+ EndPointL1SubStateCapMask = 0;
+ EndPointL1sCommonModeRestoreTime = 0;
+ EndPointL1sTpowerOnScale = 0;
+ EndPointL1sTpowerOnValue = 0;
+ EndPointL1Substates = 0;
+
+ if (RootL1SubstateExtCapOffset != 0) {
+ ///
+ /// Get the endpoint supports L1 Substates Capabilities
+ ///
+ GetOverrideL1sCapOffsetAndValue (
+ EndPointBase,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ &EndPointL1SubStateCapOffset,
+ &EndPointL1SubStateCapMask,
+ &EndPointL1sCommonModeRestoreTime,
+ &EndPointL1sTpowerOnScale,
+ &EndPointL1sTpowerOnValue
+ );
+
+ if (EndPointL1SubStateCapOffset == 0) {
+ EndPointL1SubStateCapOffset = PcieFindExtendedCapId (
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ V_PCIE_EX_L1S_CID
+ );
+ }
+ if (EndPointL1SubStateCapOffset != 0) {
+ EndPointL1Substates = MmioRead32 (EndPointBase + EndPointL1SubStateCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ }
+ }
+
+ DeviceCapabilities2 = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP2_OFFSET);
+ if (((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) == 0) || (RootPortConfig->LtrEnable != TRUE)) {
+ *RpAndEndPointsLtrSupported = FALSE;
+ }
+ ///
+ /// Configure downstream device if present.
+ ///
+ if (Operation == CalculateAspm || Operation == ManualAspm) {
+ if ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM) != B_PCIE_LCAP_CPM) {
+ *ClkreqPerPortSupported = FALSE;
+ }
+ EndPointAspm = (MmioRead16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) >> N_PCIE_LCAP_APMS) & 3;
+ DEBUG ((DEBUG_INFO, "Endpoint Device %0x Capability ASPM: %0x\n", DeviceIndex, EndPointAspm));
+ if (Operation == CalculateAspm) {
+ ///
+ /// Check endpoint for pre-1.1 devices based on the Role based Error Reporting Capability bit
+ /// and enable Aspm Override
+ ///
+ if (!(MmioRead16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & BIT15)) {
+ DEBUG ((DEBUG_INFO, "Override root port ASPM to L1 for pre-1.1 devices\n"));
+ *AspmOverride = TRUE;
+ }
+ GetOverrideAspm (
+ EndPointBase,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ &EndPointAspm
+ );
+ AspmCheckExitLatency (
+ EndPointBase,
+ EndPointPcieCapOffset,
+ RootDeviceBase,
+ RootPcieCapOffset,
+ &EndPointAspm
+ );
+ }
+
+ *LinkAspmVal &= EndPointAspm;
+ DEBUG ((DEBUG_INFO, "Calculate Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, EndPointAspm));
+ ///
+ /// Check if the endpoint supports L1 Substates Capabilities
+ ///
+ if ((EndPointL1SubStateCapOffset != 0) && (RootL1SubstateExtCapOffset != 0)) {
+ ///
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and program the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on
+ /// Pcie root port.
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and program the highest value
+ /// advertised between PCIe root port and device.to L1 Sub-States Extended Capability Offset + 0x08 [7:0] on
+ /// both Pcie root port and device.
+ /// c. Program L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// d. Program L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ /// e. Program the L1 PM Sub-States Control 1 Register bits 3:0 to the smallest common subset supported by both sides.
+ ///
+ if (((UINT8) EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask) {
+ *L1SubstatesSupported = TRUE;
+ if (EndPointL1sTpowerOnValue == 0) {
+ EndPointL1sCommonModeRestoreTime = (EndPointL1Substates >> 8) & 0xFF;
+ EndPointL1sTpowerOnScale = (EndPointL1Substates >> 16) & 0x3;
+ EndPointL1sTpowerOnValue = (EndPointL1Substates >> 19) & 0x1F;
+ }
+
+ if (EndPointL1SubStateCapMask == 0) {
+ *PortL1SubstateCapSupport &= (UINT32) (EndPointL1Substates & 0x0F);
+ } else {
+ *PortL1SubstateCapSupport &= (UINT32) EndPointL1SubStateCapMask;
+ }
+
+ if (EndPointL1sCommonModeRestoreTime > *PortCommonModeRestoreTime) {
+ *PortCommonModeRestoreTime = EndPointL1sCommonModeRestoreTime;
+ }
+
+ if (((UINT32) EndPointL1sTpowerOnValue * mPcieL1sTposMultiplier[EndPointL1sTpowerOnScale]) >
+ (*PortTpowerOnValue * mPcieL1sTposMultiplier[*PortTpowerOnScale])) {
+ *PortTpowerOnValue = EndPointL1sTpowerOnValue;
+ *PortTpowerOnScale = EndPointL1sTpowerOnScale;
+ }
+ }
+ }
+ ///
+ /// For each device detected, scan the LTR override table
+ /// If there are endpoints connected directly to the rootport then
+ /// LtrOverrideVal will be replaced by the value from the table for that endpoint
+ /// If there are endpoints that are behind a bridge and that are also part of the table then
+ /// LtrOverrideVal will maintain the minimum of all such values.
+ /// A non zero value of LtrOverrideVal will indicate:
+ /// i):That there is atleast one entry in the LTR override Table
+ /// ii):The final value to be programmed in offset 0x400. This value will be applied for all the devices
+ /// connected to this root port
+ ///
+ GetLtrOverride (
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ LtrOverrideVal,
+ ForceLtrOverride
+ );
+ } else if (Operation == SetAspm) {
+ if ((EndPointL1SubStateCapOffset != 0) && (*L1SubstatesSupported)) {
+ ///
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and program the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on
+ /// Pcie root port.
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and program the highest value
+ /// advertised between PCIe root port and device.to L1 Sub-States Extended Capability Offset + 0x08 [7:0] on
+ /// both Pcie root port and device.
+ /// c. Program L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// d. Program L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ /// e. Program the L1 PM Sub-States Control 1 Register bits 3:0 to the smallest common subset supported by both sides.
+ ///
+ if ((((UINT8) EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask)) {
+
+ //
+ // Check if current device is a downstream port
+ //
+ DownstreamPort = FALSE;
+ PcieEndCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if ((MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET) == PCI_CLASS_BRIDGE) && (PcieEndCapOffset != 0)) {
+ PcieEndDeviceType = (MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT;
+ if (PcieEndDeviceType == 0x06) {
+ DownstreamPort = TRUE;
+ }
+ }
+ ConfigureL1s (
+ DownstreamPort,
+ EndPointBase,
+ EndPointL1SubStateCapOffset,
+ *PortL1SubstateCapSupport,
+ *PortCommonModeRestoreTime,
+ *PortTpowerOnValue,
+ *PortTpowerOnScale
+ );
+ }
+ }
+ ///
+ /// Write it to the Link Control register
+ ///
+ DEBUG ((DEBUG_INFO, "Program Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, *LinkAspmVal));
+ MmioAndThenOr16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCTL_OFFSET, (UINT16) ~B_PCIE_LCTL_ASPM, *LinkAspmVal);
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3
+ ///
+ ConfigureLtr (
+ RootPortConfig,
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ EndPointBase,
+ EndPointPcieCapOffset,
+ DeviceCapabilities2,
+ PchSeries,
+ LtrOverrideVal
+ );
+ }
+ ///
+ /// Check if this device is a bridge
+ ///
+ ClassCode = MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET);
+
+ if (ClassCode == PCI_CLASS_BRIDGE) {
+ ///
+ /// Get the downstream Bus number
+ ///
+ DownStreamBusMin = MmioRead8 (EndPointBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ///
+ /// If the Secondary Bus Number of endpoint device is not assigned
+ ///
+ if (DownStreamBusMin == 0) {
+ RootDevSubBusNum = MmioRead8 (RootDeviceBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ ///
+ /// If the endpoint device is a bridge, the Subordinate Bus Number of the root port will need to be greater
+ /// than the Secondary Bus Number of the root port (the Bus Number of endpoint device).
+ ///
+ if (RootDevSubBusNum > EndPointBus) {
+ ///
+ /// Assign the Primary, Secondary and Subordinate Bus Number to endpoint device
+ ///
+ MmioAndThenOr32 (
+ EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF000000,
+ EndPointBus | (((UINT32) (EndPointBus + 1) << 8)) | ((UINT32) (RootDevSubBusNum << 16))
+ );
+ DownStreamBusMin = EndPointBus + 1;
+ } else {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BusAssign = FALSE;
+ } else {
+ BusAssign = TRUE;
+ }
+
+ if (DownStreamBusMin > EndPointBus) {
+ Status = PcieEndPointPm (
+ RootDeviceBase,
+ RootPcieCapOffset,
+ DownStreamBusMin,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ LinkAspmVal,
+ Operation,
+ LtrOverrideVal,
+ RootL1SubstateExtCapOffset,
+ L1SubstatesSupported,
+ PortL1SubstateCapSupport,
+ PortCommonModeRestoreTime,
+ PortTpowerOnValue,
+ PortTpowerOnScale,
+ RootPortConfig,
+ AspmOverride,
+ ClkreqPerPortSupported,
+ RpAndEndPointsLtrSupported,
+ ForceLtrOverride
+ );
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_INFO, "Check DownStreamBus:%d and no device found!\n", DownStreamBusMin));
+ }
+
+ if (BusAssign == FALSE) {
+ ///
+ /// Clear Bus Numbers.
+ ///
+ MmioAnd32 (EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] CurrentPortBus Pci Bus Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] CurrentPortDevice Pci Device Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] CurrentPortFunc Pci Function Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in, out] MaxPayload The Max Payolad Size of the root port
+ @param[in] SetConfig FALSE to Get information or TRUE to set configuration
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 CurrentPortBus,
+ IN UINT8 CurrentPortDevice,
+ IN UINT8 CurrentPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN SetConfig,
+ IN BOOLEAN EnableCpm
+ )
+{
+ UINT32 Index;
+ UINTN CurrentDeviceBase;
+ UINTN EndPointBase;
+ UINT8 EndPointBus;
+ UINT8 PcieCapOffset;
+ UINT8 PcieDeviceType;
+ UINT8 PcieEndCapOffset;
+ UINT8 PcieEndDeviceType;
+ UINT16 SlotStatus;
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices RootBDF %0x : %0x :%0x\n",RootPortBus, RootPortDevice, RootPortFunc));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices CurrentBDF %0x : %0x :%0x\n",CurrentPortBus, CurrentPortDevice, CurrentPortFunc));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices TempBusMin %0x , TempBusMax %0x\n",TempBusNumberMin, TempBusNumberMax));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices MaxPayLoad %0x\n", *MaxPayload));
+ CurrentDeviceBase = MmPciBase (CurrentPortBus, CurrentPortDevice, CurrentPortFunc);
+ ///
+ /// Get the downstream Bus number
+ ///
+ EndPointBus = MmioRead8 (CurrentDeviceBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ///
+ /// If the Secondary Bus Number of the root port is not assigned,
+ /// then temporarily Hardcode the Root Port Bridge Number to TempBusNumberMin,
+ /// otherwise use the assigned Bus Number
+ ///
+ if (EndPointBus == 0) {
+ MmioAndThenOr32 (
+ CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF000000,
+ CurrentPortBus | ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16))
+ );
+ } else {
+ TempBusNumberMin = EndPointBus;
+ TempBusNumberMax = MmioRead8 (CurrentDeviceBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ }
+ PcieCapOffset = PcieFindCapId (
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+ PcieDeviceType = (UINT8) ((MmioRead16 (CurrentDeviceBase + PcieCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+
+ ///
+ /// Skip this section if Upstream device
+ ///
+ if ((PcieDeviceType != 0x05) ||
+ ((MmioRead8 (CurrentDeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE)) {
+ ///
+ /// This Endpoint check should immediately pass.
+ /// Completion Retry Status Replay Enable is set in PchRootPorts.c PchInitRootPorts ()
+ /// to bypass the timing requirements of the PCI Express Base
+ /// Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s
+ /// after a reset of a device, before it may determine that a device which
+ /// fails to return a Successful Completion status for a valid Configuration
+ /// Request is a broken device").
+ ///
+ EndPointBase = MmPciBase (TempBusNumberMin, 0, 0);
+ ///
+ /// A config write is required in order for the device to re-capture the Bus number,
+ /// according to PCI Express Base Specification, 2.2.6.2 ("Note that the Bus Number
+ /// and Device Number may be changed at run time, and so it is necessary to re-capture
+ /// this information with each and every Configuration Write Request")
+ ///
+ MmioWrite8 (EndPointBase + 0x0, 0);
+
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ ///
+ /// Clear Bus Numbers.
+ ///
+ if (EndPointBus == 0) {
+ MmioAnd32 (CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ return EFI_NOT_FOUND;
+ }
+ }
+ for (Index = 0; Index <= PCI_MAX_DEVICE; Index++) {
+ EndPointBase = MmPciBase (TempBusNumberMin, Index, 0);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+
+ if (!SetConfig) {
+ ///
+ /// Get the Max Payload Size on all the end point functions
+ ///
+ PcieMaxPayloadSize (TempBusNumberMin, (UINT8) Index, MaxPayload, FALSE);
+ }
+
+ PcieEndCapOffset = PcieFindCapId (
+ TempBusNumberMin,
+ (UINT8) Index,
+ 0,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+
+ ///
+ /// Check if this device is a bridge
+ /// Pcie to Pci/PciX bridges are skipped
+ ///
+ if ((MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET) == PCI_CLASS_BRIDGE) && (PcieEndCapOffset != 0)) {
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices Bridge Detected\n"));
+ PcieEndDeviceType = (UINT8) ((MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+ SlotStatus = MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_SLSTS_OFFSET);
+
+ ///
+ /// Initialize the downstream device in following conditions:
+ /// PcieDeviceType is 5 (endpoint is an upstream device).
+ /// PcieDeviceType is 6 (endpoint is a downstream device). And the slot has a device.
+ ///
+ if ((PcieEndDeviceType == 0x05) || ((PcieEndDeviceType == 0x06) && ((SlotStatus & B_PCIE_SLSTS_PDS) != 0))) {
+ ///
+ /// Initialize downstream devices
+ ///
+ if (TempBusNumberMax > TempBusNumberMin) {
+ PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ TempBusNumberMin,
+ (UINT8) Index,
+ 0,
+ TempBusNumberMin + 1,
+ TempBusNumberMax,
+ MaxPayload,
+ SetConfig,
+ EnableCpm
+ );
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+
+ if (SetConfig) {
+ ///
+ /// Disable the forwarding of EOI messages unless it discovers an IOAPIC behind this root port
+ ///
+ if (CurrentPortBus == DEFAULT_PCI_BUS_NUMBER_PCH) {
+ PcieSetEoiFwdDisable (CurrentPortBus, CurrentPortDevice, CurrentPortFunc, TempBusNumberMin, (UINT8) Index);
+ }
+
+ ///
+ /// Set Common Clock for inserted cards
+ ///
+ ///
+ /// PCH BIOS Spec Section 8.3 ASPM on DMI and the PCI Express* Root Ports
+ /// Before determining whether ASPM can be enabled or not,
+ /// the System BIOS must perform the following steps:
+ ///
+ /// For PCH H
+ /// 1. Update the Link Capabilities of the DMI link to indicate L0s/L1 is
+ /// supported by programming the LCAP Register,
+ /// PCR[DMI] + 21A4h[11:10] = 11b. (for PCH with DMI ONLY)
+ /// (Done in PchDmiPei.c)
+ ///
+ /// 2. Enable L0s on DMI for Desktop platforms by setting the APMC field,
+ /// PCR[DMI] + 21A8h[1:0] to 01b.
+ /// Enable L0s/L1 on DMI by setting PCR[DMI] + 21A8h[1:0] to 11b. (for PCH with DMI ONLY)
+ /// (Done in PchDmiPei.c)
+ ///
+ /// 3. For each root port, read the Slot Clock Configuration bit, Dxx:Fn:52h[12],
+ /// of the root port and the endpoint device connected to the port (i.e., D0:F0 on the
+ /// secondary bus behind the root port). If both components have this bit set, then the
+ /// System BIOS should set the Common Clock Configuration (CCC) bit, Dxx:Fn:50h[6],
+ /// for both components at both sides of the link to indicate that components at both ends
+ /// of the link use a common clock source.
+ ///
+ /// 4. If the CCC bit was changed by the System BIOS in step 3, System BIOS should initiate
+ /// a link training by setting the Retrain Link (RL) bit, Dxx:Fn:50h[5], and then poll the Link
+ /// Training (LT) bit, Dxx:Fn:52h[11], until it is clear.
+ /// Note that System BIOS should save and restore CCC bit on S3.
+ ///
+ PcieSetCommonClock (CurrentPortBus, CurrentPortDevice, CurrentPortFunc, TempBusNumberMin, (UINT8) Index);
+
+ ///
+ /// Enable the PCIe CLKREQ#
+ ///
+ if (EnableCpm) {
+ PcieSetClkreq (TempBusNumberMin, (UINT8) Index, RootPortDevice, RootPortFunc);
+ }
+
+ ///
+ /// Set the Max Payload Size on all the end point functions
+ ///
+ PcieMaxPayloadSize (TempBusNumberMin, (UINT8) Index, MaxPayload, TRUE);
+ }
+ }
+
+ ///
+ /// Clear Bus Numbers if it's not assigned yet
+ ///
+ if (EndPointBus == 0) {
+ MmioAnd32 (CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitRootPortDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN BOOLEAN EnableCpm
+ )
+{
+ UINT16 SlotStatus;
+ UINTN RpBase;
+ UINT16 MaxPayload;
+ UINT8 PcieCapOffset;
+ EFI_STATUS Status;
+ UINT8 CurrentPortBus;
+ UINT8 CurrentPortDevice;
+ UINT8 CurrentPortFunc;
+ UINT32 Timeout;
+
+
+ RpBase = MmPciBase (RootPortBus, RootPortDevice, RootPortFunc);
+ ///
+ /// Check for a Presence Detect Change.
+ ///
+ SlotStatus = MmioRead16 (RpBase + R_PCH_PCIE_SLSTS);
+
+ ///
+ /// Check whether the slot has a device connected
+ ///
+ if ((SlotStatus & B_PCIE_SLSTS_PDS) == 0) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Make sure the link is active before trying to talk to device behind it
+ /// Wait up to 100ms, according to PCIE spec chapter 6.7.3.3
+ ///
+ Timeout = 100 * 1000;
+ while ((MmioRead16 (RpBase + R_PCH_PCIE_LSTS) & B_PCIE_LSTS_LA) == 0 ) {
+ MicroSecondDelay (10);
+ Timeout-=10;
+ if (Timeout == 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ ///
+ /// Get the pointer to the Endpoint PCI Express Capability Structure.
+ ///
+ PcieCapOffset = PcieFindCapId (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+ if (PcieCapOffset == 0) {
+ DEBUG ((DEBUG_INFO,"PcieCapOffset Not Found"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the root port Max Payload Size support
+ //
+ MaxPayload = MmioRead16 (RpBase + PcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS;
+
+ ///
+ /// Initialize downstream devices
+ ///
+ CurrentPortBus = RootPortBus;
+ CurrentPortDevice = RootPortDevice;
+ CurrentPortFunc = RootPortFunc;
+
+ //
+ // Get configuration from all downstreams
+ //
+ // In current implementation, only the MaxPayloadSize need to be calculated.
+ // Therefore, for performance, skip the calculation if the MaxPayloadSize is already minimum.
+ //
+ if (MaxPayload != 0) {
+ Status = PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ TempBusNumberMin,
+ TempBusNumberMax,
+ &MaxPayload,
+ FALSE,
+ EnableCpm
+ );
+ }
+ //
+ // Set configuration to all downstreams
+ //
+ Status = PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ TempBusNumberMin,
+ TempBusNumberMax,
+ &MaxPayload,
+ TRUE,
+ EnableCpm
+ );
+ return Status;
+}
+
+/**
+ Get current PCIe link speed.
+
+ @param[in] RpBase Root Port base address
+ @return Link speed
+**/
+UINT32
+GetLinkSpeed (
+ UINTN RpBase
+ )
+{
+ return MmioRead16 (RpBase + R_PCH_PCIE_LSTS) & B_PCIE_LSTS_CLS;
+}
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port base address
+ @return Max link speed
+**/
+UINT32
+GetMaxLinkSpeed (
+ UINTN RpBase
+ )
+{
+ return MmioRead32 (RpBase + R_PCH_PCIE_LCAP) & B_PCIE_LCAP_MLS;
+}
+
+/**
+ Get Pch Maximum Pcie Controller Number
+
+ @retval Pch Maximum Pcie Controller Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPcieControllerNum (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return PCH_LP_PCIE_MAX_CONTROLLERS;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ return KBL_PCH_H_PCIE_MAX_CONTROLLERS;
+ } else {
+ return SKL_PCH_H_PCIE_MAX_CONTROLLERS;
+ }
+ }
+}
+
+/**
+ PCIe controller configuration strings.
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8* mPcieControllerConfigName[] = {
+ "4x1",
+ "1x2-2x1",
+ "2x2",
+ "1x4"
+};
+
+/**
+ Returns the PCIe controller configuration (4x1, 1x2-2x1, 2x2, 1x4)
+
+ @param[in] ControllerIndex Number of PCIe controller (0 based)
+
+ @retval PCIe controller configuration
+**/
+PCIE_CONTROLLER_CONFIG
+GetPcieControllerConfig (
+ IN UINT32 ControllerIndex
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ PCIE_CONTROLLER_CONFIG Config;
+ UINT32 FirstRp;
+
+ FirstRp = ControllerIndex * PCH_PCIE_CONTROLLER_PORTS;
+
+ Status = PchSbiRpPciRead32 (FirstRp, R_PCH_PCIE_STRPFUSECFG, &Data32);
+ ASSERT_EFI_ERROR (Status);
+
+ Config = ((Data32 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ DEBUG ((DEBUG_INFO, "PCIe SP%c is %a\n", (UINTN) ('A' + ControllerIndex), mPcieControllerConfigName[Config]));
+ return Config;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
new file mode 100644
index 0000000000..bd59b5346e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
@@ -0,0 +1,45 @@
+/** @file
+ Header file for PCH Pci Express helps library implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_
+#define _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchPolicyCommon.h>
+#include <PchAccess.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/PchInitCommonLib.h>
+
+#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9)
+#define LTR_SCALE_MASK (BIT10 + BIT11 + BIT12)
+
+ #define CONFIG_WRITE_LOOP_COUNT 100000
+
+//
+// LTR related macros
+//
+#define LTR_LATENCY_VALUE(x) ((x) & LTR_VALUE_MASK)
+#define LTR_SCALE_VALUE(x) (((x) & LTR_SCALE_MASK) >> 10)
+#define LTR_LATENCY_NS(x) (LTR_LATENCY_VALUE(x) * (1 << (5 * LTR_SCALE_VALUE(x))))
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
new file mode 100644
index 0000000000..b02f311f02
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
@@ -0,0 +1,52 @@
+## @file
+# Component description file for the PeiDxeSmmPchPciExpressHelpersLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPciExpressHelpersLib
+FILE_GUID = 07E3F76D-6D26-419d-9053-58696A15B519
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPciExpressHelpersLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+IoLib
+DebugLib
+PchPcieRpLib
+PchPcrLib
+PchInfoLib
+GpioLib
+TimerLib
+PchPsfPrivateLib
+PchInitCommonLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+PchPciExpressHelpersLibrary.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
new file mode 100644
index 0000000000..ef579c825d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
@@ -0,0 +1,1169 @@
+/** @file
+ This file contains PSF routines for RC usage
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/S3BootScriptLib.h>
+
+/**
+ This procedure will disable CIO2 device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableCio2Device (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Hide CIO2 devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideCio2Device (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ Disable HDAudio device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableHdaDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_AUD_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable xDCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXdciDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable xHCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXhciDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SATA device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSataDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable ISH device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable ISH BAR1 at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshBar1 (
+ VOID
+ )
+{
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // ISH device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ Disable GbE device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableGbeDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+ PCH_SBI_PID PortId;
+
+ if (GetPchSeries () == PchLp) {
+ PortId = PID_PSF1;
+ RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ PortId = PID_PSF3;
+ RegOffset = R_PCH_H_PCR_PSF3_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PortId,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SMBUS device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSmbusDevice (
+ VOID
+ )
+{
+ ///
+ /// Hide SMBUS device
+ /// Set PCR[PSF_3] + "AGNT_T0_SHDW_CFG_DIS"[SMBUS][0]
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+
+ ///
+ /// Function disable SMBUS device
+ /// Set PCR[PSF_3] + "AGNT_T0_SHDW_PCIEN"[SMBUS][8]
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable Thermal device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableThermalDevice (
+ VOID
+ )
+{
+ ///
+ /// Set PCR[PSF2] TRH PCIEN[8] to 1
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Hide Thermal device PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideThermalDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpScsDevicePsfRegBase[] =
+{
+ R_PCH_LP_PCR_PSF2_T0_SHDW_EMMC_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_SDIO_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_SDCARD_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_UFS_REG_BASE
+};
+
+/**
+ Disable SCS device at PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsDevice (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ )
+{
+ if (ScsDevNum >= PchPsfMaxScsDevNum) {
+ ASSERT (FALSE);
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SCS devices BAR1 PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsBar1 (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ )
+{
+ if (ScsDevNum >= PchPsfMaxScsDevNum) {
+ ASSERT (FALSE);
+ }
+
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // SCS device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ Hide TraceHub ACPI devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubAcpiDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will hide TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will reveal TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfRevealTraceHubDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS),
+ 0
+ );
+}
+
+/**
+ This procedure will disable and hide TraceHub device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableTraceHubDevice (
+ VOID
+ )
+{
+ PsfHideTraceHubDevice ();
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Calculates offset of PCR register where given rootport can be enabled/disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval Offset
+**/
+static UINT16
+GetPsfPcieRootPortOffset (
+ IN UINT32 RpIndex
+ )
+{
+ UINT16 RootPortReg;
+
+ if (GetPchSeries () == PchLp) {
+ RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ }
+ }
+ return (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN);
+}
+
+/**
+ Re-enable PCIe Root Port at PSF level after it was disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRootPort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), (UINT32)(~B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS), 0);
+}
+
+/**
+ Disable PCIe Root Port at PSF level
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), ~0u, B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS);
+}
+
+/**
+ Disable PCIe Root Port at PSF level.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPortWithS3BootScript (
+ IN UINT32 RpIndex
+ )
+{
+ UINT16 RootPortReg;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ if (GetPchSeries () == PchLp) {
+ if (RpIndex >= PCH_LP_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ if (RpIndex >= KBL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (RpIndex >= SKL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ }
+ }
+
+ Data32And = ~0u;
+ Data32Or = B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS;
+
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN,
+ Data32And,
+ Data32Or
+ );
+
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSF1, (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN),
+ &Data32Or,
+ &Data32And
+ );
+}
+
+/**
+ Program PSF grant counts for PCI express depending on controllers configuration
+
+ @param[in] Controller PCIe controller index
+ @param[in] ControllerConfig Port configuration of controller
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurePcieGrantCounts (
+ UINT8 Controller,
+ UINT8 ControllerConfig
+ )
+{
+ static CONST UINT8 DgcrPairsLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
+ { { 5, 6 }, { 8, 9 }, { 11, 12 }, { 14, 15 } }, //SPA
+ { { 19, 20 }, { 22, 23 }, { 25, 26 }, { 28, 29 } }, //SPB
+ { { 33, 34 }, { 36, 37 }, { 39, 40 }, { 42, 43 } }, //SPC
+ };
+
+ static CONST UINT8 PgTgtLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
+ { 4, 5, 6, 7 }, //SPA
+ { 12, 13, 14, 15 }, //SPB
+ { 20, 21, 22, 23 } //SPC
+ };
+
+ static CONST UINT8 DgcrPairsH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
+ { { 11, 12 }, { 14, 15 }, { 17, 18 }, { 20, 21 } }, //SPA
+ { { 24, 25 }, { 27, 28 }, { 30, 31 }, { 33, 34 } }, //SPB
+ { { 37, 38 }, { 40, 41 }, { 43, 44 }, { 46, 47 } }, //SPC
+ { { 50, 51 }, { 53, 54 }, { 56, 57 }, { 59, 60 } }, //SPD
+ { { 63, 64 }, { 66, 67 }, { 69, 70 }, { 72, 73 } }, //SPE
+ { {182,183 }, {185,186 }, {188,189 }, {191,192 } } //SPF, only for KBL-H
+ };
+
+ static CONST UINT8 PgTgtH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
+ { 0, 1, 2, 3 }, //SPA
+ { 4, 5, 6, 7 }, //SPB
+ { 12, 13, 14, 15 }, //SPC
+ { 20, 21, 22, 23 }, //SPD
+ { 28, 29, 30, 31 }, //SPE
+ { 32, 33, 34, 35 } //SPF, only for KBL-H
+ };
+
+ static CONST UINT8 DefaultGrantCount = 4;
+
+ PCH_SERIES PchSeries;
+ UINT32 Dgcr0Addr;
+ UINT32 PgTgt0Addr;
+ UINT32 DgcrNo0;
+ UINT32 DgcrNo1;
+ UINT32 PgTgtNo;
+ UINT32 Channel;
+ UINT32 ChannelGrant[PCH_PCIE_CONTROLLER_PORTS];
+
+ DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts(%d) Start\n", Controller));
+
+ PchSeries = GetPchSeries ();
+ if (PchSeries == PchLp) {
+ Dgcr0Addr = R_PCH_LP_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_PCH_LP_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ Dgcr0Addr = R_KBL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_KBL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ } else {
+ Dgcr0Addr = R_SKL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_SKL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ }
+ }
+
+
+ switch (ControllerConfig) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1: //Pcie4x1
+ ChannelGrant[0] = 1;
+ ChannelGrant[1] = 1;
+ ChannelGrant[2] = 1;
+ ChannelGrant[3] = 1;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: //Pcie1x2_2x1
+ ChannelGrant[0] = 2;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = 1;
+ ChannelGrant[3] = 1;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: //Pcie2x2
+ ChannelGrant[0] = 2;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = 2;
+ ChannelGrant[3] = DefaultGrantCount;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4: //Pcie1x4
+ ChannelGrant[0] = 4;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = DefaultGrantCount;
+ ChannelGrant[3] = DefaultGrantCount;
+ break;
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Channel = 0; Channel < PCH_PCIE_CONTROLLER_PORTS; ++Channel) {
+ if (PchSeries == PchLp) {
+ DgcrNo0 = DgcrPairsLp[Controller][Channel][0];
+ DgcrNo1 = DgcrPairsLp[Controller][Channel][1];
+ PgTgtNo = PgTgtLp[Controller][Channel];
+ } else {
+ DgcrNo0 = DgcrPairsH[Controller][Channel][0];
+ DgcrNo1 = DgcrPairsH[Controller][Channel][1];
+ PgTgtNo = PgTgtH[Controller][Channel];
+ }
+
+ DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo0, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (Dgcr0Addr + (DgcrNo0 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
+ (UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo1, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (Dgcr0Addr + (DgcrNo1 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
+ (UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ DEBUG ((DEBUG_INFO, "PG1_TGT%d = %d\n", PgTgtNo, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (PgTgt0Addr + (PgTgtNo * S_PCH_PSF_TARGET_GNTCNT_RELOAD)),
+ (UINT32) ~B_PCH_PSF_TARGET_GNTCNT_RELOAD_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ }
+
+ DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable ISM NP Completion Tracking for GbE PSF port
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIsmNpCompletionTrackForGbe (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+ PCH_SBI_PID PortId;
+
+ if (GetPchSeries () == PchLp) {
+ PortId = PID_PSF1;
+ RegOffset = R_PCH_LP_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7;
+ } else {
+ PortId = PID_PSF3;
+ RegOffset = R_PCH_H_PCR_PSF3_PSF_PORT_CONFIG_PG1_PORT1;
+ }
+ ///
+ /// Clear PCR PSF_x_PSF_PORT_CONFIG_PGx_PORTx[5] = 0b
+ ///
+ PchPcrAndThenOr8 (
+ PortId,
+ RegOffset,
+ (UINT8) ~(BIT5),
+ 0
+ );
+}
+
+/**
+ Program PSF EOI Multicast configuration
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfSetEoiMulticastConfiguration (
+ VOID
+ )
+{
+ UINT32 McastTarget;
+
+ ///
+ /// Program PSF Multicast registers accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ if (GetPchSeries () == PchLp) {
+ McastTarget = V_PCH_LP_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
+ ///
+ /// Set PCR[PSF1] + 4060h = 38A00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 4050h[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ } else {
+ McastTarget = V_PCH_H_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
+ if (GetPchGeneration () == KblPch) {
+ ///
+ /// Set PCR[PSF1] + 405Ch = 38B00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 404Ch[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ } else {
+ ///
+ /// Set PCR[PSF1] + 4058h = 38B00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 4048h[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ }
+ }
+ ///
+ /// Set PCR[PSF1] + 4054h to P2SB target
+ ///
+ PchPcrWrite32 (
+ PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF3] + 404Ch[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+}
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ )
+{
+
+ UINT32 Data32;
+ UINT8 NumMcVal;
+ UINT32 RpDestId;
+ ///
+ /// PCH-LP:
+ /// RP Destination ID RP Destination ID
+ /// 1 0x18100 7 0x18302
+ /// 2 0x18101 8 0x18303
+ /// 3 0x18102 9 0x18500
+ /// 4 0x18103 10 0x18501
+ /// 5 0x18300 11 0x18502
+ /// 6 0x18301 12 0x18503
+ ///
+ static UINT32 PchSklLpRpDestId[PCH_LP_PCIE_MAX_ROOT_PORTS] =
+ {
+ 0x18100, 0x18101, 0x18102, 0x18103, 0x18300,
+ 0x18301, 0x18302, 0x18303, 0x18500, 0x18501,
+ 0x18502, 0x18503
+ };
+ ///
+ /// PCH-H:
+ /// RP Destination ID RP Destination ID
+ /// 1 0x18000 11 0x18302
+ /// 2 0x18001 12 0x18303
+ /// 3 0x18002 13 0x18500
+ /// 4 0x18003 14 0x18501
+ /// 5 0x18100 15 0x18502
+ /// 6 0x18101 16 0x18503
+ /// 7 0x18102 17 0x18700
+ /// 8 0x18103 18 0x18701
+ /// 9 0x18300 19 0x18702
+ /// 10 0x18301 20 0x18703
+ ///
+ /// KBL-H: same as SKL-H plus the following 4 ports
+ /// 21 0x18800 23 0x18802
+ /// 22 0x18801 24 0x18803
+ ///
+ static UINT32 PchHRpDestId[KBL_PCH_H_PCIE_MAX_ROOT_PORTS] =
+ {
+ 0x18000, 0x18001, 0x18002, 0x18003,
+ 0x18100, 0x18101, 0x18102, 0x18103,
+ 0x18300, 0x18301, 0x18302, 0x18303,
+ 0x18500, 0x18501, 0x18502, 0x18503,
+ 0x18700, 0x18701, 0x18702, 0x18703,
+ 0x18800, 0x18801, 0x18802, 0x18803
+ };
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+ UINT16 PsfReg;
+
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+
+ ///
+ /// If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ /// accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ ///
+ ///
+ ///
+ /// Read PSF_1_PSF_MC_CONTROL_MCAST0_RS0_EOI bit [7:1], increase it by 1, write back
+ ///
+ if (PchSeries == PchLp) {
+ PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ } else {
+ if (PchGen == KblPch) {
+ PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ } else {
+ PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ }
+ }
+ PchPcrRead32 (PID_PSF1, PsfReg, &Data32);
+ NumMcVal = (UINT8) (Data32 >> 1);
+ Data32 += 0x2;
+ PchPcrWrite32 (PID_PSF1, PsfReg, Data32);
+
+ ///
+ /// Program PSF_1_PSF_MC_AGENT_MCAST0_RS0_TGT<x>_EOI, the next empty register,
+ /// where x is the same as the value read in step 1 before the increment.
+ /// Program this register according to the RP# and the table below
+ ///
+ if (PchSeries == PchLp) {
+ PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ RpDestId = PchSklLpRpDestId[RpIndex];
+ } else {
+ if (PchGen == KblPch) {
+ PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ } else {
+ PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ }
+ RpDestId = PchHRpDestId[RpIndex];
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, PsfReg + (NumMcVal * 4),
+ (UINT32) ~0,
+ RpDestId
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reload default RP PSF device number and function number.
+ The PSF register doesn't got reset after system reset, which will result in mismatch between
+ PSF register setting and PCIE PCR PCD register setting. Reset PSF register in early phase
+ to avoid cycle decoding confusing.
+
+ @param[in] None
+
+ @retval Status
+**/
+VOID
+PsfReloadDefaultPcieRpDevFunc (
+ VOID
+ )
+{
+ UINT16 Psf1RpFuncCfgBase;
+ UINTN PortIndex;
+ UINTN MaxPciePorts;
+
+ PortIndex = 0;
+ MaxPciePorts = GetPchMaxPciePortNum ();
+
+ if (GetPchSeries () == PchLp) {
+ Psf1RpFuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ Psf1RpFuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ Psf1RpFuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ }
+ }
+ //
+ // Reload D28 registers
+ //
+ for (; PortIndex < 8; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+ //
+ // Reload D29 registers
+ //
+ for (; PortIndex < 16 && PortIndex < MaxPciePorts; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+ //
+ // Reload D27 registers
+ //
+ for (; PortIndex < MaxPciePorts; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+}
+
+
+/**
+ Assign new function number for PCIe Port Number.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+ @param[in] NewFunction New Function number
+
+ @retval None
+**/
+VOID
+PsfSetPcieFunctionWithS3BootScript (
+ IN UINT32 RpIndex,
+ IN UINT32 NewFunction
+ )
+{
+ UINT16 PsfRpFuncCfgBase;
+ UINT16 PsfD28F0FuncCfgBase;
+ UINT32 Data32;
+
+ if (GetPchSeries () == PchLp) {
+ PsfD28F0FuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ PsfD28F0FuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ PsfD28F0FuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ }
+ }
+
+ PsfRpFuncCfgBase = PsfD28F0FuncCfgBase + 4 * (UINT16)RpIndex;
+
+ //
+ // Program PSF1 RP function config register.
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ PsfRpFuncCfgBase,
+ (UINT32) ~B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION,
+ (UINT32) (NewFunction << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+
+ PchPcrRead32 (PID_PSF1, PsfRpFuncCfgBase, &Data32);
+ PCH_PCR_BOOT_SCRIPT_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSF1,
+ PsfRpFuncCfgBase,
+ 1,
+ &Data32
+ );
+}
+
+/**
+ This function enables PCIe Relaxed Order in PSF
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRelaxedOrder (
+ VOID
+ )
+{
+ ///
+ /// PCH BIOS Spec Section 8.2.9
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_PCR_PSF_PORT_CONFIG_PG0_PORT0,
+ ~0u,
+ BIT1
+ );
+}
+
+/**
+ Configure PSF power management.
+ Must be called after all PSF configuration is completed.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfConfigurePowerManagement (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (PID_PSF1, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+}
+
+/**
+ Enable VTd support in PSF.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchPsfEnableVtd (
+ VOID
+ )
+{
+ STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
+ UINTN PsfPidIndex;
+
+ for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
+ ~0u,
+ B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_VTDEN
+ );
+ }
+}
+
+/**
+ Disable PSF address-based peer-to-peer decoding.
+**/
+VOID
+PchPsfDisableP2pDecoding (
+ VOID
+ )
+{
+ STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
+ UINTN PsfPidIndex;
+
+ for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
+ (UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
+ 0
+ );
+
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS1,
+ (UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
+ 0
+ );
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf
new file mode 100644
index 0000000000..6995171b10
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf
@@ -0,0 +1,47 @@
+## @file
+# Component description file for the PeiDxeSmmPchPsfPrivateLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPsfPrivateLib
+FILE_GUID = 7A6C18CA-0353-433E-885D-DD68BFAD38BE
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPsfPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchInfoLib
+ PchPcrLib
+ PchPcieRpLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+ PchPsfPrivateLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c
new file mode 100644
index 0000000000..ad5c784bff
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c
@@ -0,0 +1,652 @@
+/** @file
+ PCH Smbus Executive Code (common PEI/DXE/SMM code)
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <IndustryStandard/SmBus.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchSmbusCommonLib.h>
+
+/**
+ Get SMBUS IO Base address
+
+
+ @retval UINT32 The SMBUS IO Base Address
+**/
+UINT32
+SmbusGetIoBase (
+ VOID
+ )
+{
+ UINT32 SmbusIoBase;
+
+ SmbusIoBase = MmioRead32 (
+ MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS)
+ + R_PCH_SMBUS_BASE) & B_PCH_SMBUS_BASE_BAR;
+
+ ASSERT (SmbusIoBase != B_PCH_SMBUS_BASE_BAR && SmbusIoBase != 0);
+
+ return SmbusIoBase;
+}
+
+/**
+ This function provides a standard way to read PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+
+ @retval UINT8 Returns data read from IO.
+**/
+UINT8
+EFIAPI
+SmbusIoRead (
+ IN UINT8 Offset
+ )
+{
+ return IoRead8 (SmbusGetIoBase () + Offset);
+}
+
+/**
+ This function provides a standard way to write PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+ @param[in] Data Data to write to register.
+
+**/
+VOID
+EFIAPI
+SmbusIoWrite (
+ IN UINT8 Offset,
+ IN UINT8 Data
+ )
+{
+ ///
+ /// Write New Value
+ ///
+ IoWrite8 (SmbusGetIoBase () + Offset, Data);
+ return;
+}
+
+/**
+ This function provides a standard way to check if an SMBus transaction has
+ completed.
+
+ @param[in] StsReg Not used for input. On return, contains the
+ value of the SMBus status register.
+
+ @retval TRUE Transaction is complete
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+IoDone (
+ IN UINT8 *StsReg
+ )
+{
+ ///
+ /// Wait for IO to complete
+ ///
+ UINTN StallIndex;
+ UINTN StallTries;
+
+ StallTries = STALL_TIME / STALL_PERIOD;
+
+ for (StallIndex = 0; StallIndex < StallTries; StallIndex++) {
+ *StsReg = SmbusIoRead (R_PCH_SMBUS_HSTS);
+ if (*StsReg & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_BYTE_DONE_STS | B_PCH_SMBUS_DERR | B_PCH_SMBUS_BERR)) {
+ return TRUE;
+ } else {
+ MicroSecondDelay (STALL_PERIOD);
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check if it's ok to use the bus.
+
+
+ @retval EFI_SUCCESS SmBus is acquired and it's safe to send commands.
+ @retval EFI_TIMEOUT SmBus is busy, it's not safe to send commands.
+**/
+EFI_STATUS
+AcquireBus (
+ VOID
+ )
+{
+ UINT8 StsReg;
+
+ StsReg = 0;
+ StsReg = SmbusIoRead (R_PCH_SMBUS_HSTS);
+ if (StsReg & B_PCH_SMBUS_IUS) {
+ return EFI_TIMEOUT;
+ } else if (StsReg & B_PCH_SMBUS_HBSY) {
+ ///
+ /// Clear Status Register and exit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ return EFI_TIMEOUT;
+ } else {
+ ///
+ /// Clear out any odd status information (Will Not Clear In Use)
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, StsReg);
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ This function provides a standard way to execute Smbus protocols
+ as defined in the SMBus Specification. The data can either be of
+ the Length byte, word, or a block of data. The resulting transaction will be
+ either the SMBus Slave Device accepts this transaction or this function
+ returns with an error
+
+ @param[in] SlaveAddress Smbus Slave device the command is directed at
+ @param[in] Command Slave Device dependent
+ @param[in] Operation Which SMBus protocol will be used
+ @param[in] PecCheck Defines if Packet Error Code Checking is to be used
+ @param[in, out] Length How many bytes to read. Must be 0 <= Length <= 32 depending on Operation
+ It will contain the actual number of bytes read/written.
+ @param[in, out] Buffer Contain the data read/written.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @exception EFI_UNSUPPORTED The operation is unsupported.
+
+ @retval EFI_INVALID_PARAMETER Length or Buffer is NULL for any operation besides
+ quick read or quick write.
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period, or the controller is not
+ available for use.
+ @retval EFI_DEVICE_ERROR There was an Smbus error (NACK) during the operation.
+ This could indicate the slave device is not present
+ or is in a hung condition.
+**/
+EFI_STATUS
+SmbusExec (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 AuxcReg;
+ UINT8 AuxStsReg;
+ UINT8 SmbusOperation;
+ UINT8 StsReg;
+ UINT8 SlvAddrReg;
+ UINT8 HostCmdReg;
+ UINT8 BlockCount;
+ BOOLEAN BufferTooSmall;
+ UINTN Index;
+ UINTN BusIndex;
+ UINT8 *CallBuffer;
+ UINT8 SmbusHctl;
+ UINT32 Timeout;
+
+ CallBuffer = Buffer;
+ BlockCount = 0;
+
+ ///
+ /// For any operations besides quick read & write, the pointers to
+ /// Length and Buffer must not be NULL.
+ ///
+ if ((Operation != EfiSmbusQuickRead) && (Operation != EfiSmbusQuickWrite)) {
+ if ((Length == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ ///
+ /// See if its ok to use the bus based upon INUSE_STS bit.
+ ///
+ Status = AcquireBus ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// This is the main operation loop. If the operation results in a Smbus
+ /// collision with another master on the bus, it attempts the requested
+ /// transaction again at least BUS_TRIES attempts.
+ ///
+ for (BusIndex = 0; BusIndex < BUS_TRIES; BusIndex++) {
+ ///
+ /// Operation Specifics (pre-execution)
+ ///
+ Status = EFI_SUCCESS;
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_QUICK;
+ SlvAddrReg = (UINT8) ((SlaveAddress.SmbusDeviceAddress << 1) | 1);
+ HostCmdReg = (UINT8) Command;
+ AuxcReg = 0;
+
+ switch (Operation) {
+
+ case EfiSmbusQuickWrite:
+ SlvAddrReg--;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusQuickRead:
+ if (PecCheck == TRUE) {
+ Status = EFI_UNSUPPORTED;
+ }
+ break;
+
+ case EfiSmbusSendByte:
+ HostCmdReg = CallBuffer[0];
+ SlvAddrReg--;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReceiveByte:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE;
+ if (*Length < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 1;
+ break;
+
+ case EfiSmbusWriteByte:
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ SlvAddrReg--;
+ *Length = 1;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReadByte:
+ if (*Length < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else if (*Length == 1) {
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
+ } else if (*Length <= 256) {
+ if (PecCheck == TRUE) {
+ ///
+ /// The I2C Read command with either PEC_EN or AAC bit set
+ /// produces undefined results.
+ ///
+ Status = EFI_UNSUPPORTED;
+ }
+
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_IIC_READ;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ break;
+
+ case EfiSmbusReadWord:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusWriteWord:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
+ SlvAddrReg--;
+ SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusWriteBlock:
+ SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
+ SlvAddrReg--;
+ BlockCount = (UINT8) (*Length);
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReadBlock:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK;
+ if ((*Length < 1) || (*Length > 32)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ AuxcReg |= B_PCH_SMBUS_E32B;
+ break;
+
+ case EfiSmbusProcessCall:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_PROCESS_CALL;
+ SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusBWBRProcessCall:
+ ///
+ /// The write byte count cannot be zero or more than
+ /// 32 bytes.
+ ///
+ if ((*Length < 1) || (*Length > 32)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
+ BlockCount = (UINT8) (*Length);
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS;
+
+ AuxcReg |= B_PCH_SMBUS_E32B;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (PecCheck == TRUE) {
+ AuxcReg |= B_PCH_SMBUS_AAC;
+ }
+ ///
+ /// Set Auxiliary Control register
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_AUXC, AuxcReg);
+
+ ///
+ /// Reset the pointer of the internal buffer
+ ///
+ SmbusIoRead (R_PCH_SMBUS_HCTL);
+
+ ///
+ /// Now that the 32 byte buffer is turned on, we can write th block data
+ /// into it
+ ///
+ if ((Operation == EfiSmbusWriteBlock) || (Operation == EfiSmbusBWBRProcessCall)) {
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Write next byte
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HBD, CallBuffer[Index]);
+ }
+ }
+ ///
+ /// Set SMBus slave address for the device to send/receive from
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_TSA, SlvAddrReg);
+
+ ///
+ /// For I2C read, send DATA1 register for the offset (address)
+ /// within the serial memory chips
+ ///
+ if ((Operation == EfiSmbusReadByte) && (*Length > 1)) {
+ SmbusIoWrite (R_PCH_SMBUS_HD1, HostCmdReg);
+ } else {
+ ///
+ /// Set Command register
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HCMD, HostCmdReg);
+ }
+ ///
+ /// Set Control Register (Initiate Operation, Interrupt disabled)
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START));
+
+ ///
+ /// Wait for IO to complete
+ ///
+ if (!IoDone (&StsReg)) {
+ Status = EFI_TIMEOUT;
+ break;
+ } else if (StsReg & B_PCH_SMBUS_DERR) {
+ AuxStsReg = SmbusIoRead (R_PCH_SMBUS_AUXS);
+ if (AuxStsReg & B_PCH_SMBUS_CRCE) {
+ Status = EFI_CRC_ERROR;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ break;
+ } else if (StsReg & B_PCH_SMBUS_BERR) {
+ ///
+ /// Clear the Bus Error for another try
+ ///
+ Status = EFI_DEVICE_ERROR;
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
+ ///
+ /// Clear Status Registers
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+ ///
+ /// If bus collision happens, stall some time, then try again
+ /// Here we choose 10 milliseconds to avoid MTCP transfer.
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ continue;
+ }
+ ///
+ /// successfull completion
+ /// Operation Specifics (post-execution)
+ ///
+ switch (Operation) {
+
+ case EfiSmbusReadWord:
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusProcessCall:
+ CallBuffer[1] = SmbusIoRead (R_PCH_SMBUS_HD1);
+ CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
+ break;
+
+ case EfiSmbusReadByte:
+ if (*Length > 1) {
+ for (Index = 0; Index < *Length; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ ///
+ /// After receiving byte n-1 (1-base) of the message, the
+ /// software will then set the LAST BYTE bit. The software
+ /// will then clear the BYTE_DONE_STS bit.
+ ///
+ if (Index == ((*Length - 1) - 1)) {
+ SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) | (UINT8) B_PCH_SMBUS_LAST_BYTE;
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
+ } else if (Index == (*Length - 1)) {
+ ///
+ /// Clear the LAST BYTE bit after receiving byte n (1-base) of the message
+ ///
+ SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) & (UINT8) ~B_PCH_SMBUS_LAST_BYTE;
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
+ }
+ ///
+ /// Clear the BYTE_DONE_STS bit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
+ ///
+ /// Check BYTE_DONE_STS bit to know if it has completed transmission
+ /// of a byte. No need to check it for the last byte.
+ ///
+ if (Index < (*Length - 1)) {
+ ///
+ /// If somehow board operates at 10Khz, it will take 0.9 ms (9/10Khz) for another byte.
+ /// Add 10 us delay for a loop of 100 that the total timeout is 1 ms to take care of
+ /// the slowest case.
+ ///
+ for (Timeout = 0; Timeout < 100; Timeout++) {
+ if ((SmbusIoRead (R_PCH_SMBUS_HSTS) & (UINT8) B_PCH_SMBUS_BYTE_DONE_STS) != 0) {
+ break;
+ }
+ ///
+ /// Delay 10 us
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ }
+
+ if (Timeout >= 100) {
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case EfiSmbusReceiveByte:
+ CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
+ break;
+
+ case EfiSmbusWriteBlock:
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
+ break;
+
+ case EfiSmbusReadBlock:
+ BufferTooSmall = FALSE;
+ ///
+ /// Find out how many bytes will be in the block
+ ///
+ BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
+ if (*Length < BlockCount) {
+ BufferTooSmall = TRUE;
+ } else {
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ }
+ }
+
+ *Length = BlockCount;
+ if (BufferTooSmall) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ break;
+
+ case EfiSmbusBWBRProcessCall:
+ ///
+ /// Find out how many bytes will be in the block
+ ///
+ BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
+ ///
+ /// The read byte count cannot be zero.
+ ///
+ if (BlockCount < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+ ///
+ /// The combined data payload (the write byte count + the read byte count)
+ /// must not exceed 32 bytes
+ ///
+ if (((UINT8) (*Length) + BlockCount) > 32) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ }
+
+ *Length = BlockCount;
+ break;
+
+ default:
+ break;
+ };
+
+ if ((StsReg & B_PCH_SMBUS_BERR) && (Status != EFI_BUFFER_TOO_SMALL)) {
+ ///
+ /// Clear the Bus Error for another try
+ ///
+ Status = EFI_DEVICE_ERROR;
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
+ ///
+ /// If bus collision happens, stall some time, then try again
+ /// Here we choose 10 milliseconds to avoid MTCP transfer.
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ continue;
+ } else {
+ break;
+ }
+ }
+ ///
+ /// Clear Status Registers and exit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+ SmbusIoWrite (R_PCH_SMBUS_AUXC, 0);
+ return Status;
+}
+
+/**
+ This function initializes the Smbus Registers.
+
+**/
+VOID
+InitializeSmbusRegisters (
+ VOID
+ )
+{
+ UINTN SmbusRegBase;
+
+ SmbusRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ ///
+ /// Enable the Smbus I/O Enable
+ ///
+ MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, (UINT8) EFI_PCI_COMMAND_IO_SPACE);
+
+ ///
+ /// Enable the Smbus host controller
+ ///
+ MmioAndThenOr8 (
+ SmbusRegBase + R_PCH_SMBUS_HOSTC,
+ (UINT8) (~(B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN)),
+ B_PCH_SMBUS_HOSTC_HST_EN
+ );
+
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf
new file mode 100644
index 0000000000..54a67614af
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchSmbusCommonLib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiDxeSmmPchSmbusCommonLib
+ FILE_GUID = 490CEB45-F3A8-41CD-89CB-C47BF7F7A4B4
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchSmbusCommonLib
+
+[Sources]
+ PchSmbusExec.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ MmPciLib
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c
new file mode 100644
index 0000000000..7436a76ec1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c
@@ -0,0 +1,216 @@
+/** @file
+ Routines for Rst remapping
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/RstPrivateLib.h>
+#include <PchPcieStorageDetectHob.h>
+
+/**
+ Checks whether device on given Root Port is remap capable
+
+ @param[in] RpNumber Root Port Number
+ @param[in] TempPciBus Temporary Pci Bus
+
+ @retval UINT8 Device Programming Interface
+**/
+UINT8
+RstGetProgInterfaceForRemapDevice (
+ IN UINT32 RpNumber,
+ IN UINT32 TempPciBus
+)
+{
+ UINTN RpDevice;
+ UINTN RpFunction;
+ UINT8 BusNumber;
+ UINTN EpBase;
+ UINT8 PiInterface;
+ UINTN RpBase;
+ UINT8 ClassCode;
+ UINT8 SubClassCode;
+
+
+ DEBUG ((DEBUG_INFO, "Detect storage device on Rp: %d\n", RpNumber));
+
+ GetPchPcieRpDevFun (RpNumber, &RpDevice, &RpFunction);
+ BusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
+ PiInterface = RST_PCIE_STORAGE_INTERFACE_NONE;
+ RpBase = MmPciBase (BusNumber, (UINT32) RpDevice, (UINT32) RpFunction);
+
+ if (MmioRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ DEBUG((DEBUG_INFO, "RstGetProgInterfaceForRemapDevices: RootPort does not exists Rp = %d\n", RpNumber));
+
+ return PiInterface;
+ }
+
+ //
+ // Assign Temporary Bus Number
+ //
+ MmioAndThenOr32 (
+ RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN,
+ ((UINT32) (TempPciBus << 8)) | ((UINT32) (TempPciBus << 16))
+ );
+
+ //
+ // A config write is required in order for the device to re-capture the Bus number,
+ // according to PCI Express Base Specification, 2.2.6.2
+ // Write to a read-only register VendorID to not cause any side effects.
+ //
+ EpBase = MmPciBase (TempPciBus, 0, 0);
+ MmioWrite16 (EpBase + PCI_VENDOR_ID_OFFSET, 0);
+
+ //
+ // Read Vendor Id to check if device exists
+ // if not clear bus number and return RST_PCIE_STORAGE_INTERFACE_NONE
+ //
+ if (MmioRead16 (EpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ MmioAnd32 (RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN);
+ return PiInterface;
+ }
+
+ ClassCode = MmioRead8 (EpBase + R_PCI_BCC_OFFSET);
+ SubClassCode = MmioRead8 (EpBase + R_PCI_SCC_OFFSET);
+ PiInterface = MmioRead8 (EpBase + R_PCI_PI_OFFSET);
+
+ if ( ClassCode == PCI_CLASS_MASS_STORAGE) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: ClassCode = %X, SubClassCode = %X, PiInterface = %X\n", ClassCode, SubClassCode, PiInterface));
+
+ if (SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) {
+ if (PiInterface == RST_PCIE_STORAGE_INTERFACE_AHCI) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: AHCI Card found on Rp: %d\n", RpNumber));
+
+ }
+ } else if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVME) {
+ if (PiInterface == RST_PCIE_STORAGE_INTERFACE_NVME) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: NVMe Card found on Rp: %d\n", RpNumber));
+
+ }
+ } else if (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: RAID Card found on Rp: %d\n", RpNumber));
+
+ PiInterface = RST_PCIE_STORAGE_INTERFACE_NVME;
+ }
+ }
+ //
+ // Clear temporary bus number
+ //
+ MmioAnd32 (RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN);
+
+ return PiInterface;
+
+}
+
+/**
+ Check the lane occupied by certain root port according to the root port number and configuration strap
+ Return 8-bit bitmap where each bit represents the lane number (e.g.: return 00000011b means the root port owns 2 lane)
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT8 Lane Occupied by the Root Port (bitmap)
+**/
+UINT8
+RstGetRpLaneOccupyMask (
+ IN UINT32 RootPortNum
+ )
+{
+ EFI_STATUS Status;
+ UINT32 CtrlNum;
+ UINT32 CtrlFirstRpNum;
+ UINT32 Data32;
+ UINT8 LaneOccupied;
+
+ LaneOccupied = 0;
+
+ CtrlNum = RootPortNum / PCH_PCIE_CONTROLLER_PORTS;
+ CtrlFirstRpNum = CtrlNum * PCH_PCIE_CONTROLLER_PORTS;
+
+ //
+ // Read the Root Port Configuration Straps for the link width, and return LaneOccupied by the Root Port accordingly
+ //
+ Status = PchSbiRpPciRead32 (CtrlFirstRpNum, R_PCH_PCIE_STRPFUSECFG, &Data32);
+ ASSERT_EFI_ERROR (Status);
+
+ switch ((Data32 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4:
+ if (RootPortNum % 4 == 0) {
+ LaneOccupied = (BIT3|BIT2|BIT1|BIT0);
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2:
+ if ((RootPortNum % 2 == 0)) {
+ LaneOccupied = (BIT1|BIT0);
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1:
+ if (RootPortNum % 4 == 0) {
+ LaneOccupied = (BIT1|BIT0);
+ } else if (RootPortNum % 4 != 1) {
+ LaneOccupied = BIT0;
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1:
+ LaneOccupied = BIT0;
+ break;
+ default:
+ break;
+ }
+
+ return LaneOccupied;
+}
+
+/**
+ Checks PCH generation and returns SATA's GCR.PLS bit number according to root port number with a PCIe storage device
+ connected to.
+
+ @param[in] RootPortNum Root port number which PCIe storage device is connected to
+
+ @retval UINT32 Number of GCR.PLS bit representing root port
+**/
+UINT32
+RstPlsBitNumber (
+ IN UINT32 RootPortNum
+ )
+{
+ if ((GetPchGeneration () == KblPch) && (RstGetCycleRouterNumber (RootPortNum) == RST_PCIE_STORAGE_CR_2)) {
+ return RootPortNum - 2 * PCH_PCIE_CONTROLLER_PORTS;
+ } else {
+ return RootPortNum;
+ }
+}
+
+/**
+ Checks if device with given PCI config space address is Intel's Stony Beach.
+
+ @param[in] EndPointPciBase Address of device's PCI config space
+
+ @retval BOOLEAN TRUE if device is Intel's Stony Beach, FALSE othrwise
+**/
+BOOLEAN
+RstIsStonyBeach (
+ IN UINTN EndPointPciBase
+ )
+{
+ UINT16 DeviceVendorId;
+ UINT16 DeviceDeviceId;
+
+ DeviceVendorId = MmioRead16 (EndPointPciBase + PCI_VENDOR_ID_OFFSET);
+ DeviceDeviceId = MmioRead16 (EndPointPciBase + PCI_DEVICE_ID_OFFSET);
+
+ if (DeviceVendorId == RST_STONY_BEACH_VENDOR_ID && DeviceDeviceId == RST_STONY_BEACH_DEVICE_ID) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf
new file mode 100644
index 0000000000..1bbcc7eda7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PCH Rst Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmRstPrivateLib
+FILE_GUID = FD2B63E7-FBBF-4D77-8A52-6702112EFDC1
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = RstPrivateLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcieRpLib
+PchInitCommonLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[Sources]
+PeiDxeSmmRstPrivateLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
new file mode 100644
index 0000000000..789b61170d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
@@ -0,0 +1,465 @@
+/** @file
+ This is the driver that initializes the Intel PCH.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInit.h"
+#include <Library/PchSerialIoLib.h>
+
+//
+// Module variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA_PROTOCOL mPchNvsAreaProtocol;
+
+extern PCH_RST_PCIE_STORAGE_DETECTION mRstPcieStorageDetection[];
+
+/**
+ Retrieve interrupt information about a PCH device from policy
+
+ @param[in] Device PCI device number
+
+ @retval PCH_DEVICE_INTERRUPT_CONFIG structure with device's interrupt information
+**/
+PCH_DEVICE_INTERRUPT_CONFIG
+GetInterruptPolicy (
+ IN PCH_SERIAL_IO_CONTROLLER Device
+ )
+{
+ PCH_DEVICE_INTERRUPT_CONFIG EmptyRecord;
+ UINT8 DevNum;
+ UINT8 FuncNum;
+ UINT8 Index;
+
+ ZeroMem (&EmptyRecord, sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
+ DevNum = GetSerialIoDeviceNumber (Device);
+ FuncNum = GetSerialIoFunctionNumber (Device);
+
+ for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
+ if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == DevNum) &&
+ (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == FuncNum)) {
+ return mPchConfigHob->Interrupt.DevIntConfig[Index];
+ }
+ }
+ return EmptyRecord;
+}
+
+/**
+ Update ASL definitions for SerialIo devices.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateSerialIoAcpiData (
+ VOID
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Index;
+
+ for (Index = 0; Index < PCH_SERIALIO_MAX_CONTROLLERS; Index++) {
+ mPchNvsAreaProtocol.Area->SMD[Index] = mPchConfigHob->SerialIo.DevMode[Index];
+ mPchNvsAreaProtocol.Area->SIR[Index] = (GetInterruptPolicy (Index)).Irq;
+ mPchNvsAreaProtocol.Area->SB0[Index] = FindSerialIoBar (Index, 0);
+ mPchNvsAreaProtocol.Area->SB1[Index] = FindSerialIoBar (Index, 1);
+ }
+ if (GetPchSeries () == PchH) {
+ mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C4] = PchSerialIoDisabled;
+ mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C5] = PchSerialIoDisabled;
+ }
+
+ //
+ // Update GPIO device ACPI variables
+ //
+ mPchNvsAreaProtocol.Area->GPEN = mPchConfigHob->SerialIo.Gpio;
+ mPchNvsAreaProtocol.Area->SGIR = mPchConfigHob->Interrupt.GpioIrqRoute;
+
+
+ DEBUG ((DEBUG_INFO, "UpdateSerialIoAcpiData() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update NVS Area after RST PCIe Storage Remapping and before Boot
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+PchUpdateNvsAreaAfterRemapping (
+ VOID
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ mPchNvsAreaProtocol.Area->RstPcieStorageInterfaceType[Index] = mRstPcieStorageDetection[Index].DeviceInterface;
+ mPchNvsAreaProtocol.Area->RstPcieStoragePmCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PmCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStoragePcieCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PcieCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageL1ssCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.L1ssCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl2[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl2;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl1[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl1;
+ mPchNvsAreaProtocol.Area->RstPcieStorageLtrCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.LtrCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpLtrData[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLtrData;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpLctlData16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLctlData16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpDctlData16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctlData16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpDctl2Data16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctl2Data16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageRpDctl2Data16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.RootPortDctl2Data16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBar[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBar;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBarValue[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBarValue;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBar[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBar;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBarValue[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBarValue;
+ mPchNvsAreaProtocol.Area->RstPcieStorageRootPortNum[Index] = mRstPcieStorageDetection[Index].RootPortNum;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ PCH ACPI initialization before Boot Sript Table is closed
+ It update ACPI table and ACPI NVS area.
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+PchAcpiOnEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+
+ PCH_SERIES PchSeries;
+
+ DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() Start\n"));
+
+ PchSeries = GetPchSeries ();
+
+ ///
+ /// 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 ();
+ //
+ // Define and update ASL definitions for Cio2 device (only on PCH-LP).
+ //
+ if (PchSeries >= PchLp) {
+ UpdateCio2AcpiData ();
+ }
+
+ //
+ // Update Pch Nvs Area
+ //
+ PchUpdateNvsArea ();
+
+ //
+ // Patch PchNvsArea Address
+ //
+ PatchPchNvsAreaAddress ();
+
+ DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() End\n"));
+
+ return;
+}
+
+/**
+ Initialize Pch acpi
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
+
+ DEBUG ((DEBUG_INFO, "Install PCH NVS protocol\n"));
+
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PCH_NVS_AREA), (VOID **) &mPchNvsAreaProtocol.Area);
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem ((VOID *) mPchNvsAreaProtocol.Area, sizeof (PCH_NVS_AREA));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPchNvsAreaProtocolGuid,
+ &mPchNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update the NVS Area after RST PCIe Storage Remapping
+ ///
+ PchUpdateNvsAreaAfterRemapping ();
+ //
+ // Register an end of DXE event for PCH ACPI to do tasks before invoking any UEFI drivers,
+ // applications, or connecting consoles,...
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ PchAcpiOnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ PCH Update NvsArea ExitBootServicesFlag on ExitBootService. This event is used if only ExitBootService is used
+ and not in legacy boot
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchUpdateNvsOnExitBootServices (
+ VOID
+ )
+{
+ mPchNvsAreaProtocol.Area->ExitBootServicesFlag = 1;
+
+ return;
+}
+
+/**
+ 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;
+ PCH_SERIES PchSeries;
+ UINTN Index;
+ UINT32 HpetBaseAdress;
+ GPIO_GROUP GroupToGpeDw0;
+ GPIO_GROUP GroupToGpeDw1;
+ GPIO_GROUP GroupToGpeDw2;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ GPIO_PAD GpioPad;
+ GPIO_PAD_OWN PadOwnVal;
+ GPIO_CONFIG GpioData;
+ UINTN RpDev;
+ UINTN RpFun;
+ UINT32 Data32;
+ UINT16 Data16;
+
+ Status = EFI_SUCCESS;
+ PchSeries = GetPchSeries ();
+
+ //
+ // Update ASL PCIE port address according to root port device and function
+ //
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ Status = GetPchPcieRpDevFun (Index, &RpDev, &RpFun);
+ ASSERT_EFI_ERROR (Status);
+
+ Data32 = ((UINT8) RpDev << 16) | (UINT8) RpFun;
+ mPchNvsAreaProtocol.Area->RpAddress[Index] = Data32;
+
+ //
+ // Update Maximum Snoop Latency and Maximum No-Snoop Latency values for PCIE
+ //
+ mPchNvsAreaProtocol.Area->PcieLtrMaxSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].LtrMaxSnoopLatency;
+ mPchNvsAreaProtocol.Area->PcieLtrMaxNoSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].LtrMaxNoSnoopLatency;
+ }
+
+ //
+ // Update PCHS.
+ //
+ mPchNvsAreaProtocol.Area->PchSeries = (UINT16) PchSeries;
+ //
+ // Update PCHG.
+ //
+ mPchNvsAreaProtocol.Area->PchGeneration = (UINT16) GetPchGeneration ();
+ //
+ // Update HPET base address.
+ //
+ PchHpetBaseGet (&HpetBaseAdress);
+ mPchNvsAreaProtocol.Area->HPTE = TRUE; // @todo remove the NVS, since it's always enabled.
+ mPchNvsAreaProtocol.Area->HPTB = HpetBaseAdress;
+ //
+ // Update SBREG_BAR.
+ //
+ mPchNvsAreaProtocol.Area->SBRG = PCH_PCR_BASE_ADDRESS;
+
+ //
+ // Update PMC ACPIBASE and PWRMBASE
+ //
+ PchAcpiBaseGet (&Data16);
+ mPchNvsAreaProtocol.Area->PMBS = Data16;
+
+ PchPwrmBaseGet (&Data32);
+ mPchNvsAreaProtocol.Area->PWRM = Data32;
+
+ //
+ // Update GPP_X to GPE_DWX mapping.
+ //
+ GpioGetGroupToGpeDwX (&GroupToGpeDw0, &GroupToGpeDw1, &GroupToGpeDw2);
+
+ //
+ // GPEM is an object for informing how GPIO groups are mapped to GPE.
+ // Mapping for GPP_x is evaluated from (GPEM >> (GroupNumber*2)) & 0x3
+ // Here GroupNumber does not match xxx_GPIO_GROUP type and is always
+ // 0 based (GPP_A = 0, both for LP and H)
+ // Possible values for each group:
+ // 00b - 2-tier
+ // 01b - 1-tier, GPE_DW0
+ // 10b - 1-tier, GPE_DW1
+ // 11b - 1-tier, GPE_DW2
+ //
+ mPchNvsAreaProtocol.Area->GPEM = (0x1 << (GpioGetGroupIndexFromGroup (GroupToGpeDw0) * 2)) |
+ (0x2 << (GpioGetGroupIndexFromGroup (GroupToGpeDw1) * 2)) |
+ (0x3 << (GpioGetGroupIndexFromGroup (GroupToGpeDw2) * 2));
+
+ //
+ // GP2T[GroupIndex] is an object for storing information about GPIO pads which are
+ // enabled for 2-tier GPE event and their interrupt is configured for level
+ // 0b - Gpio Pad which is not 2-tier event or hasn't got level interrupt
+ // 1b - Gpio Pad enabled for 2-tier event and having level interrupt
+ //
+ for (Group = GpioGetLowestGroup (); Group <= GpioGetHighestGroup (); Group++) {
+ Index = GpioGetGroupIndexFromGroup (Group);
+ if (Index >= sizeof (mPchNvsAreaProtocol.Area->GP2T) / sizeof (mPchNvsAreaProtocol.Area->GP2T[0])) {
+ DEBUG ((DEBUG_ERROR, "GpioGetGroupIndexFromGroup (%x) = %x out of GP2T table range\n", Group, GpioGetGroupIndexFromGroup (Group)));
+ continue;
+ }
+ mPchNvsAreaProtocol.Area->GP2T[Index] = 0x0;
+
+ if ((Group == GroupToGpeDw0) ||
+ (Group == GroupToGpeDw1) ||
+ (Group == GroupToGpeDw2)) {
+ //
+ // not 2-tier GPE
+ //
+ continue;
+ }
+
+ for (PadNumber = 0; PadNumber < GpioGetPadPerGroup (Group); PadNumber++) {
+
+ GpioPad = GpioGetGpioPadFromGroupAndPadNumber (Group, PadNumber);
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ continue;
+ }
+
+ GpioGetPadConfig (GpioPad, &GpioData);
+
+ if (((GpioData.InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) == GpioIntSci) &&
+ ((GpioData.InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) == GpioIntLevel)) {
+ //
+ // This pad is enabled for GPE and has level interrupt
+ //
+ mPchNvsAreaProtocol.Area->GP2T[Index] |= 1 << PadNumber;
+ }
+ }
+ }
+
+ //
+ // Thermal device in ACPI mode
+ //
+ mPchNvsAreaProtocol.Area->ThermalDeviceAcpiEnabled = mPchConfigHob->Thermal.ThermalDeviceEnable == 2 ? 1 : 0;
+ //
+ // Get Thermal Device interrupt line number
+ //
+ for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
+ if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == PCI_DEVICE_NUMBER_PCH_THERMAL) &&
+ (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == PCI_FUNCTION_NUMBER_PCH_THERMAL)) {
+ mPchNvsAreaProtocol.Area->ThermalDeviceInterruptLine = mPchConfigHob->Interrupt.DevIntConfig[Index].Irq;
+ }
+ }
+
+ //
+ // SCS Configuration
+ //
+ // Update eMMC HS400 mode enablement
+ //
+ mPchNvsAreaProtocol.Area->EMH4 = (UINT8) mPchConfigHob->Scs.ScsEmmcHs400Enabled;
+
+ //
+ // Update eMMC Driver Strength
+ // Per eMMC 5.01 JEDEC Specification (JESD84-B50.1, Table 186)
+ // Nominal Impedance - Driver Type Values:
+ // 50 Ohm 0x0
+ // 33 Ohm 0x1
+ // 40 Ohm 0x4
+ //
+ switch (mPchConfigHob->Scs.ScsEmmcHs400DriverStrength) {
+ case DriverStrength33Ohm:
+ mPchNvsAreaProtocol.Area->EMDS = 0x1;
+ break;
+ case DriverStrength40Ohm:
+ mPchNvsAreaProtocol.Area->EMDS = 0x4;
+ break;
+ case DriverStrength50Ohm:
+ default:
+ mPchNvsAreaProtocol.Area->EMDS = 0x0;
+ }
+
+ //
+ // CPU SKU
+ //
+ mPchNvsAreaProtocol.Area->CpuSku = GetCpuSku ();
+
+ return Status;
+}
+
+/**
+ Initialize PCH Nvs Area opeartion region.
+
+ @retval EFI_SUCCESS initialized successfully
+ @retval EFI_NOT_FOUND Nvs Area operation region is not found
+**/
+EFI_STATUS
+PatchPchNvsAreaAddress (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ UINT16 Length;
+
+ Status = InitializeAslUpdateLib ();
+ ASSERT_EFI_ERROR (Status);
+
+ Address = (UINT32) (UINTN) mPchNvsAreaProtocol.Area;
+ Length = (UINT16) sizeof (PCH_NVS_AREA);
+ DEBUG ((DEBUG_INFO, "PatchPchNvsAreaAddress: PCH NVS Address %x Length %x\n", Address, Length));
+ Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','B'), &Address, sizeof (Address));
+ ASSERT_EFI_ERROR (Status);
+ Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','L'), &Length, sizeof (Length));
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c
new file mode 100644
index 0000000000..f0abea1323
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c
@@ -0,0 +1,57 @@
+/** @file
+ Initializes PCH CIO2 device ACPI data.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PchInit.h>
+
+/**
+ Update ASL definitions for CIO2 device.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateCio2AcpiData (
+ VOID
+ )
+{
+ UINT32 Index;
+ PCH_STEPPING PchStep;
+
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() Start\n"));
+ PchStep = PchStepping ();
+
+ //if CIO2 is enabled as ACPI device then update its ACPI data
+ if (PchStep >= PchLpC0) {
+ mPchNvsAreaProtocol.Area->Cio2EnabledAsAcpiDevice = 0;
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() Cio2 has not been enabled as ACPI device\n"));
+ } else {
+ mPchNvsAreaProtocol.Area->Cio2EnabledAsAcpiDevice = 0;
+ if (mPchConfigHob->Cio2.DeviceEnable == 1) {
+ mPchNvsAreaProtocol.Area->Cio2EnabledAsAcpiDevice = 1;
+ for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
+ if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == PCI_DEVICE_NUMBER_PCH_CIO2) &&
+ (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == PCI_FUNCTION_NUMBER_PCH_CIO2)) {
+ mPchNvsAreaProtocol.Area->Cio2IrqNumber = mPchConfigHob->Interrupt.DevIntConfig[Index].Irq;
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() Cio2 has been enabled as ACPI device. Irq number = 0x%x\n", mPchConfigHob->Interrupt.DevIntConfig[Index].Irq));
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
new file mode 100644
index 0000000000..732dc8905d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
@@ -0,0 +1,247 @@
+/** @file
+ Initializes the PCH HD Audio ACPI Tables.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PchInit.h>
+#include <Guid/Acpi.h>
+#include <Library/PcdLib.h>
+#include <Library/PchHdaLib.h>
+
+PCH_HDA_NHLT_ENDPOINTS mPchHdaNhltEndpoints[HdaEndpointMax] =
+{
+ {HdaDmicX1, B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT, FALSE},
+ {HdaDmicX2, (B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT), FALSE},
+ {HdaDmicX4, (B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT), FALSE},
+ {HdaBtRender, (B_HDA_BT_NARROWBAND_FORMAT | B_HDA_BT_WIDEBAND_FORMAT | B_HDA_BT_A2DP_FORMAT), FALSE},
+ {HdaBtCapture, (B_HDA_BT_NARROWBAND_FORMAT | B_HDA_BT_WIDEBAND_FORMAT), FALSE},
+ {HdaI2sRender1, (B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT), FALSE},
+ {HdaI2sRender2, (B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT), FALSE},
+ {HdaI2sCapture, (B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT), FALSE}
+};
+
+/**
+ Retrieves address of NHLT table from XSDT/RSDT.
+
+ @retval NHLT_ACPI_TABLE* Pointer to NHLT table if found
+ @retval NULL NHLT could not be found
+**/
+NHLT_ACPI_TABLE *
+LocateNhltAcpiTable (
+ VOID
+ )
+{
+ EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+ EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
+ NHLT_ACPI_TABLE *Nhlt;
+ UINTN Index;
+ UINT64 Data64;
+ EFI_STATUS Status;
+ Rsdp = NULL;
+ Xsdt = NULL;
+ Nhlt = NULL;
+
+ ///
+ /// Find the AcpiSupport protocol returns RSDP (or RSD PTR) address.
+ ///
+ DEBUG ((DEBUG_INFO, "LocateNhltAcpiTable() Start\n"));
+
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID *) &Rsdp);
+ if (EFI_ERROR (Status) || (Rsdp == NULL)) {
+ DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n"));
+ return NULL;
+ }
+
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
+ if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ // If XSDT has not been found, check RSDT
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
+ if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "XSDT/RSDT == NULL or wrong signature\n"));
+ return NULL;
+ }
+ }
+
+ for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Xsdt->Length; Index = Index + sizeof (UINT64)) {
+ Data64 = *(UINT64 *) ((UINT8 *) Xsdt + Index);
+ Nhlt = (NHLT_ACPI_TABLE *) (UINTN) Data64;
+ if (Nhlt->Header.Signature == NHLT_ACPI_TABLE_SIGNATURE) {
+ break;
+ }
+ }
+
+ if (Nhlt == NULL || Nhlt->Header.Signature != NHLT_ACPI_TABLE_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "Nhlt == NULL or wrong signature\n"));
+ return NULL;
+ }
+
+ DEBUG ((DEBUG_INFO, "Found NhltTable, Address = 0x%016x\n", Nhlt));
+
+ return Nhlt;
+}
+
+/**
+ Constructs and installs NHLT table.
+
+ @retval EFI_SUCCESS ACPI Table installed successfully
+ @retval EFI_UNSUPPORTED ACPI Table protocol not found
+**/
+EFI_STATUS
+PublishNhltAcpiTable (
+ VOID
+ )
+{
+ UINTN AcpiTableKey;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ NHLT_ACPI_TABLE *NhltTable;
+ UINT32 TableLength;
+ EFI_STATUS Status;
+
+ AcpiTable = NULL;
+ NhltTable = NULL;
+ AcpiTableKey = 0;
+
+ DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() Start\n"));
+
+ //
+ // Locate ACPI support protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+ if ( EFI_ERROR (Status) || AcpiTable == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ NhltConstructor (mPchHdaNhltEndpoints, &NhltTable, &TableLength);
+ NhltAcpiHeaderConstructor (NhltTable, TableLength);
+
+ Status = AcpiTable->InstallAcpiTable (AcpiTable, NhltTable, NhltTable->Header.Length, &AcpiTableKey);
+
+ DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() End\n"));
+ return Status;
+}
+
+/**
+ Sets NVS ACPI variables for _DSM accordingly to policy.
+
+ @param[in] NhltAcpiTableAddress
+ @param[in] NhltAcpiTableLength
+ @param[in] DspFeatureMask
+**/
+VOID
+UpdateHdaAcpiData (
+ IN UINT64 NhltAcpiTableAddress,
+ IN UINT32 NhltAcpiTableLength,
+ IN UINT32 DspFeatureMask
+ )
+{
+ DEBUG ((DEBUG_INFO, "UpdateHdaAcpiData():\n NHLT Address = 0x%016x, Length = 0x%08x\n", NhltAcpiTableAddress, NhltAcpiTableLength));
+ DEBUG ((DEBUG_INFO, " FeatureMask = 0x%08x\n", DspFeatureMask));
+
+ mPchNvsAreaProtocol.Area->NHLA = NhltAcpiTableAddress;
+ mPchNvsAreaProtocol.Area->NHLL = NhltAcpiTableLength;
+ mPchNvsAreaProtocol.Area->ADFM = DspFeatureMask;
+}
+
+/**
+ Initialize and publish NHLT (Non-HDA Link Table), update NVS variables.
+
+ @param[in] *HdaConfig
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+SetHdaAcpiTable (
+ IN CONST HDAUDIO_HOB *HdaConfig
+ )
+{
+ NHLT_ACPI_TABLE *NhltTable;
+ EFI_STATUS Status;
+ NhltTable = NULL;
+
+
+ switch (HdaConfig->DspEndpointDmic) {
+ case PchHdaDmic1chArray:
+ mPchHdaNhltEndpoints[HdaDmicX1].Enable = TRUE;
+ break;
+ case PchHdaDmic2chArray:
+ mPchHdaNhltEndpoints[HdaDmicX2].Enable = TRUE;
+ break;
+ case PchHdaDmic4chArray:
+ mPchHdaNhltEndpoints[HdaDmicX4].Enable = TRUE;
+ break;
+ case PchHdaDmicDisabled:
+ default:
+ mPchHdaNhltEndpoints[HdaDmicX2].Enable = FALSE;
+ mPchHdaNhltEndpoints[HdaDmicX4].Enable = FALSE;
+ }
+
+ if (HdaConfig->DspEndpointBluetooth) {
+ mPchHdaNhltEndpoints[HdaBtRender].Enable = TRUE;
+ mPchHdaNhltEndpoints[HdaBtCapture].Enable = TRUE;
+ }
+
+ if (HdaConfig->DspEndpointI2s) {
+ mPchHdaNhltEndpoints[HdaI2sRender1].Enable = TRUE;
+ mPchHdaNhltEndpoints[HdaI2sRender2].Enable = TRUE;
+ mPchHdaNhltEndpoints[HdaI2sCapture].Enable = TRUE;
+ }
+
+ Status = PublishNhltAcpiTable ();
+ NhltTable = LocateNhltAcpiTable ();
+ if (NhltTable == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ UpdateHdaAcpiData ((UINT64) (UINTN) NhltTable, (UINT32) (NhltTable->Header.Length), HdaConfig->DspFeatureMask);
+
+ DEBUG_CODE ( NhltAcpiTableDump (NhltTable); );
+ return Status;
+}
+
+/**
+ Initialize Intel High Definition Audio ACPI Tables
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_LOAD_ERROR ACPI table cannot be installed
+ @retval EFI_UNSUPPORTED ACPI table not set because DSP is disabled
+**/
+EFI_STATUS
+PchHdAudioAcpiInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CONST HDAUDIO_HOB *HdaConfig;
+ UINTN HdaPciBase;
+
+ DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() Start\n"));
+
+ HdaConfig = &mPchConfigHob->HdAudio;
+
+ HdaPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_HDA,
+ PCI_FUNCTION_NUMBER_PCH_HDA
+ );
+
+ if ((MmioRead16 (HdaPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) || (HdaConfig->DspEnable == FALSE)) {
+ // Do not set ACPI tables if HDAudio is Function disabled or DSP is disabled
+ DEBUG ((DEBUG_INFO, "AudioDSP: Non-HDAudio ACPI Table (NHLT) not set!\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = SetHdaAcpiTable (HdaConfig);
+
+ DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() End - Status = %r\n", Status));
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
new file mode 100644
index 0000000000..0428479b50
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
@@ -0,0 +1,504 @@
+/** @file
+ This is the Common driver that initializes the Intel PCH.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInit.h"
+
+//
+// Module variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *mPchConfigHob;
+GLOBAL_REMOVE_IF_UNREFERENCED SI_CONFIG_HOB *mSiConfigHob;
+
+/**
+ Common PchInit Module Entry Point
+**/
+VOID
+PchInitEntryPointCommon (
+ VOID
+ )
+{
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() Start\n"));
+
+ //
+ // Get PCH Config HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gPchConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ //
+ // Get Silicon Config data HOB
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gSiConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mSiConfigHob = (SI_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() End\n"));
+
+ return;
+}
+
+/**
+ Lock USB registers before boot
+
+ @param[in] PchConfigHob The PCH Config HOB
+**/
+VOID
+LockXhciConfiguration (
+ IN CONST PCH_CONFIG_HOB *PchConfigHob
+ )
+{
+ UINTN XhciPciMmBase;
+ UINT32 XhccCfg;
+
+ DEBUG ((DEBUG_INFO, "LockXhciConfiguration () - Start\n"));
+
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ ///
+ /// PCH BIOS Spec Section 13.2.4 Locking xHCI Register Settings
+ /// PCH BIOS Spec Locking xHCI Register settings
+ /// After xHCI is initialized, BIOS should lock the xHCI configuration registers to RO.
+ /// This prevent any unintended changes. There is also a lockdown feature for OverCurrent
+ /// registers. BIOS should set these bits to lock down the settings prior to end of POST.
+ /// 1. Set Access Control bit at XHCI PCI offset 40h[31] to 1b to lock xHCI register settings.
+ /// 2. Set OC Configuration Done bit at XHCI PCI offset 44h[31] to lock overcurrent mappings from
+ /// further changes.
+ ///
+ MmioOr32 (XhciPciMmBase + R_PCH_XHCI_XHCC2, (UINT32) (BIT31));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC2),
+ 1,
+ (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC2)
+ );
+
+ ///
+ /// PCH BIOS Spec xHCI controller setup
+ /// Note:
+ /// XHCI PCI offset 40h is write once register.
+ /// Unsupported Request Detected bit is write clear
+ ///
+ XhccCfg = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_XHCC1);
+ XhccCfg &= (UINT32) ~(B_PCH_XHCI_XHCC1_URD);
+ XhccCfg |= (UINT32) (B_PCH_XHCI_XHCC1_ACCTRL);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_XHCC1, XhccCfg);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC1),
+ 1,
+ (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC1)
+ );
+
+ DEBUG ((DEBUG_INFO, "LockXhciConfiguration () - End\n"));
+}
+
+/**
+ Process all the lock downs
+**/
+VOID
+ProcessAllLocks (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT8 Data8;
+ UINT16 Data16And;
+ UINT16 Data16Or;
+ UINT32 Data32;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT32 DlockValue;
+ UINTN PciLpcRegBase;
+ UINTN PciSpiRegBase;
+ UINTN PciPmcRegBase;
+ UINT16 TcoBase;
+ UINT32 PchPwrmBase;
+ UINTN PchSpiBar0;
+
+ PciLpcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ PciPmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ PciSpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ PchSpiBar0 = MmioRead32 (PciSpiRegBase + R_PCH_SPI_BAR0) &~(B_PCH_SPI_BAR0_MASK);
+
+ PchTcoBaseGet (&TcoBase);
+
+ //
+ // Lock XHCI configuration
+ //
+ LockXhciConfiguration (mPchConfigHob);
+
+ ///
+ /// Set PWRMBASE + 620h [31] to lock the ST and NST PG register fields.
+ ///
+ ConfigurePmcStaticFunctionDisableLock ();
+
+ ///
+ /// SKL PCH BWG 7.2.4 Additional PCH DMI and OP-DMI Programming Steps
+ /// Step 9.2
+ /// Set PCR[DMI] + 2234h [31] = 1b.
+ /// Leave this in DXE since setting it in PEI would break the ActiveBIOS module.
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCR_DMI_DMIC_SRL;
+ PchPcrAndThenOr32 (
+ PID_DMI, R_PCH_PCR_DMI_DMIC,
+ Data32And,
+ Data32Or
+ );
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, R_PCH_PCR_DMI_DMIC,
+ &Data32Or,
+ &Data32And
+ );
+
+
+ ///
+ /// Program the Flash Protection Range Register based on policy
+ ///
+ DlockValue = MmioRead32 (PchSpiBar0 + R_PCH_SPI_DLOCK);
+ for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) {
+ if ((mPchConfigHob->ProtectRange[Index].WriteProtectionEnable ||
+ mPchConfigHob->ProtectRange[Index].ReadProtectionEnable) != TRUE) {
+ continue;
+ }
+
+ ///
+ /// Proceed to program the register after ensure it is enabled
+ ///
+ Data32 = 0;
+ Data32 |= (mPchConfigHob->ProtectRange[Index].WriteProtectionEnable == TRUE) ? B_PCH_SPI_PRX_WPE : 0;
+ Data32 |= (mPchConfigHob->ProtectRange[Index].ReadProtectionEnable == TRUE) ? B_PCH_SPI_PRX_RPE : 0;
+ Data32 |= ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRangeLimit << N_PCH_SPI_PRX_PRL) & B_PCH_SPI_PRX_PRL_MASK;
+ Data32 |= ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRangeBase << N_PCH_SPI_PRX_PRB) & B_PCH_SPI_PRX_PRB_MASK;
+ DEBUG ((DEBUG_INFO, "Protected range %d: 0x%08x \n", Index, Data32));
+
+ DlockValue |= (UINT32) (B_PCH_SPI_DLOCK_PR0LOCKDN << Index);
+ MmioWrite32 ((UINTN) (PchSpiBar0 + (R_PCH_SPI_PR0 + (Index * S_PCH_SPI_PRX))), Data32);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + (R_PCH_SPI_PR0 + (Index * S_PCH_SPI_PRX))),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + (R_PCH_SPI_PR0 + (Index * S_PCH_SPI_PRX)))
+ );
+ }
+ //
+ // Program DLOCK register
+ //
+ MmioWrite32 ((UINTN) (PchSpiBar0 + R_PCH_SPI_DLOCK), DlockValue);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_PCH_SPI_DLOCK),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_PCH_SPI_DLOCK)
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// In PCH SPI controller the BIOS should set the Flash Configuration Lock-Down bit
+ /// (SPI_BAR0 + 04[15]) at end of post. When set to 1, those Flash Program Registers
+ /// that are locked down by this FLOCKDN bit cannot be written.
+ /// Please refer to the EDS for which program registers are impacted.
+ ///
+ MmioOr32 ((UINTN) (PchSpiBar0 + R_PCH_SPI_HSFSC), (UINT32) (B_PCH_SPI_HSFSC_FLOCKDN));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_PCH_SPI_HSFSC),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_PCH_SPI_HSFSC)
+ );
+
+ ///
+ /// 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_PCH_SPI_SFDP0_VSCC0), B_PCH_SPI_SFDP0_VSCC0_VCL);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0)
+ );
+
+ ///
+ /// Additional Power Management Programming
+ /// Step 3
+ /// Set GEN_PMCON_LOCK register, PMC PCI offset A6h = 06h, after stretch and ACPI base programming completed.
+ ///
+ MmioOr8 (
+ (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B + 2),
+ (UINT8) ((B_PCH_PMC_GEN_PMCON_B_SLPSX_STR_POL_LOCK | B_PCH_PMC_GEN_PMCON_B_ACPI_BASE_LOCK) >> 16)
+ );
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B + 2),
+ 1,
+ (VOID *) (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B + 2)
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by setting
+ /// SPI/eSPI/LPC PCI offset DCh[1] = 1b.
+ /// When this bit is set, attempts to write the BIOS Write Enable (BIOSWE) bit
+ /// in PCH will cause a SMI which will allow the BIOS to verify that the write is
+ /// from a valid source.
+ /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] = 0b to enable
+ /// BIOS region protection before exiting the SMI handler.
+ /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 1b) to keep
+ /// BLE feature enabled after booting to the OS.
+ /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to
+ /// ensure SMM protection of flash.
+ /// Left to platform code to register a callback function to handle BiosWp SMI
+ ///
+ if (mPchConfigHob->LockDown.BiosLock == TRUE) {
+ //
+ // eSPI/LPC
+ //
+ if (! (MmioRead8 (PciLpcRegBase + R_PCH_LPC_BC) & B_PCH_LPC_BC_LE)) {
+ DEBUG ((DEBUG_INFO, "Set LPC bios lock\n"));
+ MmioOr8 ((UINTN) (PciLpcRegBase + R_PCH_LPC_BC), B_PCH_LPC_BC_LE);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciLpcRegBase + R_PCH_LPC_BC),
+ 1,
+ (VOID *) (UINTN) (PciLpcRegBase + R_PCH_LPC_BC)
+ );
+ }
+ //
+ // SPI
+ //
+ if (! (MmioRead8 (PciSpiRegBase + R_PCH_SPI_BC) & B_PCH_SPI_BC_LE)) {
+ DEBUG ((DEBUG_INFO, "Set SPI bios lock\n"));
+ MmioOr8 ((UINTN) (PciSpiRegBase + R_PCH_SPI_BC), (UINT8) B_PCH_SPI_BC_LE);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_PCH_SPI_BC),
+ 1,
+ (VOID *) (UINTN) (PciSpiRegBase + R_PCH_SPI_BC)
+ );
+ }
+ }
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple locations
+ /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset DCh[7]).
+ /// Setting these bits will prevent writes to the Top Swap bit (under their respective locations)
+ /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious software
+ /// attempts to replace the system BIOS option ROM with its own code.
+ ///
+ if (mPchConfigHob->LockDown.BiosInterface == TRUE) {
+ ///
+ /// LPC
+ ///
+ MmioOr8 ((UINTN) (PciLpcRegBase + R_PCH_LPC_BC), (UINT32) B_PCH_LPC_BC_BILD);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciLpcRegBase + R_PCH_LPC_BC),
+ 1,
+ (VOID *) (UINTN) (PciLpcRegBase + R_PCH_LPC_BC)
+ );
+
+ ///
+ /// Reads back for posted write to take effect
+ ///
+ Data8 = MmioRead8 ((UINTN) (PciLpcRegBase + R_PCH_LPC_BC));
+ S3BootScriptSaveMemPoll (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciLpcRegBase + R_PCH_LPC_BC),
+ &Data8, // BitMask
+ &Data8, // BitValue
+ 1, // Duration
+ 1 // LoopTimes
+ );
+
+ ///
+ /// SPI
+ ///
+ MmioOr8 ((UINTN) (PciSpiRegBase + R_PCH_SPI_BC), (UINT32) B_PCH_SPI_BC_BILD);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_PCH_SPI_BC),
+ 1,
+ (VOID *) (UINTN) (PciSpiRegBase + R_PCH_SPI_BC)
+ );
+
+ ///
+ /// Reads back for posted write to take effect
+ ///
+ Data8 = MmioRead8 ((UINTN) (PciSpiRegBase + R_PCH_SPI_BC));
+ S3BootScriptSaveMemPoll (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_PCH_SPI_BC),
+ &Data8, // BitMask
+ &Data8, // BitValue
+ 1, // Duration
+ 1 // LoopTimes
+ );
+
+ ///
+ /// Set PCR[DMI] + 274C[0] = 1b
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCR_DMI_BILD;
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_PCR_DMI_GCS, Data32And, Data32Or);
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, R_PCH_PCR_DMI_GCS,
+ &Data32Or,
+ &Data32And
+ );
+ }
+
+ ///
+ /// PCH BIOS Spec Section 5.13 BIOS guide on using RTC RAM
+ /// For Data integrity protection, set RTC Memory locks (Upper 128 Byte Lock and
+ /// Lower 128 Byte Lock) at SBCR[RTC] + 3400h[4] and SBCR[RTC] + 3400h[3]. Note once locked
+ /// bytes 0x38 - 0x3F in each of the Upper and Lower Byte blocks, respectively,
+ /// cannot be unlocked until next reset.
+ ///
+ if (mPchConfigHob->LockDown.RtcLock == TRUE) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (B_PCH_PCR_RTC_CONF_UCMOS_LOCK | B_PCH_PCR_RTC_CONF_LCMOS_LOCK | B_PCH_PCR_RTC_CONF_RESERVED);
+ PchPcrAndThenOr32 (
+ PID_RTC, R_PCH_PCR_RTC_CONF,
+ Data32And,
+ Data32Or
+ );
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_RTC, R_PCH_PCR_RTC_CONF,
+ &Data32Or,
+ &Data32And
+ );
+ }
+
+ ///
+ /// Lock Down TCO
+ ///
+ Data16And = 0xFFFF;
+ Data16Or = B_PCH_TCO_CNT_LOCK;
+ IoOr16 (TcoBase + R_PCH_TCO1_CNT, Data16Or);
+ S3BootScriptSaveIoReadWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (TcoBase + R_PCH_TCO1_CNT),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ ///
+ /// PCH BIOS Spec Section 5.15.1 Additional Chipset Initialization
+ /// Step 1
+ /// Set SPIBAR0 + F0h [0] to 1b
+ ///
+ MmioOr8 ((UINTN) (PchSpiBar0 + R_PCH_SPI_SSML), B_PCH_SPI_SSML_SSL);
+
+ //
+ // Lock Down PMC
+ // Set PWRM + 0x18 [27, 22] prior to OS.
+ //
+ PchPwrmBaseGet (&PchPwrmBase);
+ Data32Or = BIT27;
+ if (mPchConfigHob->Pm.PmcReadDisable) {
+ Data32Or |= BIT22;
+ }
+ MmioOr32 (PchPwrmBase + R_PCH_PWRM_CFG, Data32Or);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchPwrmBase + R_PCH_PWRM_CFG),
+ 1,
+ (VOID *) (UINTN) (PchPwrmBase + R_PCH_PWRM_CFG)
+ );
+}
+
+/**
+ Set eSPI BME bit
+**/
+VOID
+ConfigureEspiBme (
+ VOID
+ )
+{
+}
+
+/**
+ Common PCH initialization before Boot Sript Table is closed
+
+**/
+VOID
+PchOnPciEnumCompleteCommon (
+ VOID
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteCommon() Start\n"));
+
+ ProcessAllLocks ();
+
+ ///
+ /// Perform remaining configuration for PCH SATA on End of DXE
+ ///
+ ConfigurePchSataOnEndOfDxe ();
+
+ ///
+ /// PSTHCTL (0xD00h[2]) = 1, PSTH IOSF Primary Trunk Clock Gating Enable (PSTHIOSFPTCGE)
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCR_PSTH_PSTHIOSFPTCGE;
+ PchPcrAndThenOr32 (PID_PSTH, R_PCH_PCR_PSTH_PSTHCTL, Data32And, Data32Or);
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSTH, R_PCH_PCR_PSTH_PSTHCTL,
+ &Data32Or,
+ &Data32And
+ );
+
+ //
+ // Set eSPI BME after PCI enumeration
+ //
+ ConfigureEspiBme ();
+
+ //
+ // This function process P2SB configuration
+ // This MUST be executed in very end of End Of Dxe
+ // All PSF access after this function will not acceptable
+ //
+ ConfigureP2sbSbiLock ((BOOLEAN) mPchConfigHob->P2sb.SbiUnlock);
+
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteCommon() End\n"));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
new file mode 100644
index 0000000000..a05697d337
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
@@ -0,0 +1,320 @@
+/** @file
+ Header file for PCH Initialization Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_INITIALIZATION_DRIVER_H_
+#define _PCH_INITIALIZATION_DRIVER_H_
+
+typedef UINT16 STRING_REF;
+#ifdef FSP_FLAG
+#include <Library/PeiServicesLib.h>
+#include <Uefi/UefiSpec.h>
+#endif
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchEspiLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/TraceHubInitLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/S3BootScriptLib.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciPlatform.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#ifndef FSP_FLAG
+#include <Library/DxeServicesTableLib.h>
+#endif
+
+#include <PchAccess.h>
+#include <SiConfigHob.h>
+#include <Protocol/PchInfo.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/AslUpdateLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/PchEmmcTuning.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Protocol/PchNvs.h>
+#include <Protocol/PcieIoTrap.h>
+#include <Library/PchInitCommonLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchPsfLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <PchConfigHob.h>
+
+typedef struct {
+ PCH_INFO_PROTOCOL PchInfo;
+} PCH_INSTANCE_PRIVATE_DATA;
+
+//
+// This struct is used to record the fields that is required to be saved and restored during RST PCIe Storage Remapping Configuration
+//
+typedef struct {
+ UINT8 PmCapPtr;
+ UINT8 PcieCapPtr;
+ UINT16 L1ssCapPtr;
+ UINT8 EndpointL1ssControl2;
+ UINT32 EndpointL1ssControl1;
+ UINT16 LtrCapPtr;
+ UINT32 EndpointLtrData;
+ UINT16 EndpointLctlData16;
+ UINT16 EndpointDctlData16;
+ UINT16 EndpointDctl2Data16;
+ UINT16 RootPortDctl2Data16;
+} PCH_RST_PCIE_STORAGE_SAVE_RESTORE;
+
+//
+// This struct is used to record the result of RST PCIe Storage detection for each RST PCIe Storage Cycle Router supported on the platform
+//
+typedef struct {
+ BOOLEAN SupportRstPcieStoragRemapping; // Indicates if RST PCIe Storage Remapping is supported and PCIe storage device is found under a Cycle Router
+ UINT8 RootPortNum; // Indicates the root port number with RST PCIe Storage Remapping remapping supported and PCIe storage device plugged on, numbering is 0-based
+ UINT8 RootPortLane; // Indicates the root port lanes occupied by the PCIe storage device with 4-bit mask
+ UINT8 DeviceInterface; // Indicates the interface of the PCIe storage device (AHCI or NVMe)
+ UINT8 IsMsixSupported; // Indicates if the PCIe storage device support MSI-X cap
+ UINT16 MsixStartingVector; // Records the starting vector of PCIe storage device's MSI-X (if supported)
+ UINT16 MsixEndingVector; // Records the ending vector of PCIe storage device's MSI-X (if supported)
+ UINT32 EndPointBarSize; // Records the PCIe storage device's BAR size
+ UINT32 EndPointUniqueMsixTableBar; // Records the PCIe storage device's MSI-X Table BAR if it supports unique MSI-X Table BAR
+ UINT32 EndPointUniqueMsixTableBarValue; // Records the PCIe storage device's MSI-X Table BAR value if it supports unique MSI-X Table BAR
+ UINT32 EndPointUniqueMsixPbaBar; // Records the PCIe storage device's MSI-X PBA BAR if it supports unique MSI-X PBA BAR
+ UINT32 EndPointUniqueMsixPbaBarValue; // Records the PCIe storage device's MSI-X PBA BAR value if it supports unique MSI-X PBA BAR
+ UINT8 EndPointBcc; // Records the PCIe storage device's Base Class Code
+ UINT8 EndPointScc; // Records the PCIe storage device's Sub Class Code
+ UINT8 EndPointPi; // Records the PCIe storage device's Programming Interface
+ PCH_RST_PCIE_STORAGE_SAVE_RESTORE PchRstPcieStorageSaveRestore; // Records the fields that is required to be saved and restored
+} PCH_RST_PCIE_STORAGE_DETECTION;
+
+//
+// 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 *mSiConfigHob;
+
+//
+// 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
+ );
+
+/**
+ Update ASL definitions for SerialIo devices.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateSerialIoAcpiData (
+ VOID
+ );
+
+/**
+ Initialize PCIE SRC clocks in ICC subsystem
+
+ @param[in] GbePortNumber Number of PCIE rootport assigned to GbE adapter
+
+**/
+VOID
+ConfigurePchPcieClocks (
+ IN UINTN GbePortNumber
+ );
+
+/**
+ Initialize Intel High Definition Audio ACPI Tables
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_LOAD_ERROR ACPI table cannot be installed
+ @retval EFI_UNSUPPORTED ACPI table not set because DSP is disabled
+**/
+EFI_STATUS
+PchHdAudioAcpiInit (
+ VOID
+ );
+
+/**
+ Configure eMMC in HS400 Mode
+
+ @param[in] This A pointer to PCH_EMMC_TUNING_PROTOCOL structure
+ @param[in] Revision Revision parameter used to verify the layout of EMMC_INFO and TUNINGDATA.
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND The item was not found
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EFIAPI
+ConfigureEmmcHs400Mode (
+ IN PCH_EMMC_TUNING_PROTOCOL *This,
+ IN UINT8 Revision,
+ IN EMMC_INFO *EmmcInfo,
+ OUT EMMC_TUNING_DATA *EmmcTuningData
+ );
+
+/**
+ Install PCH EMMC TUNING PROTOCOL
+
+**/
+VOID
+InstallPchEmmcTuningProtocol (
+ VOID
+ );
+
+/**
+ Perform the remaining configuration on PCH SATA to perform device detection,
+ then set the SATA SPD and PxE corresponding, and set the Register Lock on PCH SATA
+
+ @retval None
+**/
+VOID
+ConfigurePchSataOnEndOfDxe (
+ VOID
+ );
+
+/**
+ Update ASL data for CIO2 Device.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateCio2AcpiData (
+ VOID
+ );
+
+/**
+ Initialize Pch acpi
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+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.
+
+ @retval EFI_SUCCESS initialized successfully
+ @retval EFI_NOT_FOUND Nvs Area operation region is not found
+**/
+EFI_STATUS
+PatchPchNvsAreaAddress (
+ VOID
+ );
+
+/**
+ PCH Update NvsArea ExitBootServicesFlag on ExitBootService. This event is used if only ExitBootService is used
+ and not in legacy boot
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchUpdateNvsOnExitBootServices (
+ VOID
+ );
+#endif // _PCH_INITIALIZATION_DRIVER_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
new file mode 100644
index 0000000000..1857b7f3c5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
@@ -0,0 +1,699 @@
+/** @file
+ This is the Uefi driver that initializes the Intel PCH.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInit.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mImageHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPcieIoTrapAddress;
+
+
+VOID
+EFIAPI
+PchOnBootToOs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+VOID
+EFIAPI
+PchOnExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+VOID
+EFIAPI
+PchOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+/**
+ BIOS W/A for Si bug on PCH stepping LpA0, LpA1, LpA2, LpB0:
+ allocates 1MB memory space for ISH BAR,
+ overrides 4KB memory allocation done by standard PCI enumarator.
+
+ @retval EFI_STATUS
+ @retval EFI_SUCCESS Allocation successful or stepping other that A0/A1/A2 (W/A not required)
+ @retval EFI_OUT_OF_RESOURCES Memory could not be allocated.
+**/
+EFI_STATUS
+AllocateIshMemorySpace (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN PciIshRegBase;
+ EFI_PHYSICAL_ADDRESS IshMemBaseAddress;
+
+ PciIshRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_ISH,
+ PCI_FUNCTION_NUMBER_PCH_ISH
+ );
+
+ if ((MmioRead16 (PciIshRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) ||
+ (GetPchSeries () == PchH) ||
+ (PchStepping () > PchLpB1)) {
+ return EFI_SUCCESS;
+ }
+
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ IshMemBaseAddress = 0xffffffff;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ N_PCH_ISH_BAR0_ALIGNMENT,
+ V_PCH_ISH_BAR0_SIZE,
+ &IshMemBaseAddress,
+ mImageHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MmioAnd16 (PciIshRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (PciIshRegBase + R_PCH_ISH_BAR0_LOW, (UINT32) IshMemBaseAddress);
+ MmioWrite32 (PciIshRegBase + R_PCH_ISH_BAR0_HIGH, 0);
+ MmioOr16 (PciIshRegBase + PCI_COMMAND_OFFSET, (UINT16) EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ DEBUG ((DEBUG_INFO, "ISH W/A: Allocated 1MB MMIO, BAR0 = 0x%08x\n", (UINT32) IshMemBaseAddress));
+ return Status;
+}
+
+
+/**
+ Process all the lock downs
+**/
+VOID
+ProcessSmiLocks (
+ VOID
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 ABase;
+ UINTN PciPmcRegBase;
+
+ PciPmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// BIOS needs to enables SMI_LOCK (PMC PCI offset A0h[4] = 1b) which prevent writes
+ /// to the Global SMI Enable bit (GLB_SMI_EN ABASE + 30h[0]). Enabling this bit will
+ /// mitigate malicious software attempts to gain system management mode privileges.
+ ///
+ if (mPchConfigHob->LockDown.GlobalSmi == TRUE) {
+ PchAcpiBaseGet (&ABase);
+ ///
+ /// Save Global SMI Enable bit setting before BIOS enables SMI_LOCK during S3 resume
+ ///
+ Data32Or = IoRead32 ((UINTN) (ABase + R_PCH_SMI_EN));
+ if ((Data32Or & B_PCH_SMI_EN_GBL_SMI) != 0) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or |= B_PCH_SMI_EN_GBL_SMI;
+ S3BootScriptSaveIoReadWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (ABase + R_PCH_SMI_EN),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+ MmioOr8 ((UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A), B_PCH_PMC_GEN_PMCON_A_SMI_LOCK);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A),
+ 1,
+ (VOID *) (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A)
+ );
+ }
+}
+
+/**
+ Do PCIE power management while resume from S3
+**/
+VOID
+ReconfigurePciePowerManagementForS3 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ PCH_PCIE_IOTRAP_PROTOCOL *PchPcieIoTrapProtocol;
+
+ Status = gBS->LocateProtocol (&gPchPcieIoTrapProtocolGuid, NULL, (VOID **) &PchPcieIoTrapProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPcieIoTrapAddress = PchPcieIoTrapProtocol->PcieTrapAddress;
+ DEBUG ((DEBUG_INFO, "PcieIoTrapAddress: %0x\n", mPcieIoTrapAddress));
+
+ if (mPcieIoTrapAddress != 0) {
+ //
+ // Save PCH PCIE IoTrap address to re-config PCIE power management setting after resume from S3
+ //
+ Data32 = PciePmTrap;
+ S3BootScriptSaveIoWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (mPcieIoTrapAddress),
+ 1,
+ &Data32
+ );
+ } else {
+ ASSERT (FALSE);
+ }
+}
+
+/**
+ This is the callback function for PCI ENUMERATION COMPLETE.
+**/
+VOID
+EFIAPI
+PchOnPciEnumComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ UINTN ThermalPciBase;
+ UINT32 PchPwrmBase;
+
+ ///
+ /// Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+ /// if it is, we will skip it until real event is triggered
+ ///
+ Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+ gBS->CloseEvent (Event);
+
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ //
+ // Allocate BAR for ISH - workaround for Si bug on stepping LpA0/A1/A2
+ //
+ AllocateIshMemorySpace ();
+
+ //
+ // Enable Thermal MSE
+ //
+ ThermalPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_THERMAL,
+ PCI_FUNCTION_NUMBER_PCH_THERMAL
+ );
+ if (MmioRead16 (ThermalPciBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF) {
+ if (((MmioRead32 (ThermalPciBase + R_PCH_THERMAL_TBAR) & B_PCH_THERMAL_TBAR_MASK) != 0) ||
+ ((MmioRead32 (ThermalPciBase + R_PCH_THERMAL_TBARH) != 0))) {
+ MmioOr8 (ThermalPciBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+ }
+
+ ReconfigurePciePowerManagementForS3 ();
+ ProcessSmiLocks ();
+#ifndef FSP_WRAPPER_FLAG
+ PchOnPciEnumCompleteCommon ();
+#endif
+}
+
+/**
+ Register callback functions for PCH DXE.
+**/
+VOID
+PchRegisterNotifications (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBoot;
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT ExitBootServicesEvent;
+ VOID *Registration;
+
+ ///
+ /// Create PCI Enumeration Completed callback for PCH
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ TPL_CALLBACK,
+ PchOnPciEnumComplete,
+ NULL,
+ &Registration
+ );
+
+ //
+ // Register a Ready to boot event to config PCIE power management setting after OPROM executed
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ PchOnReadyToBoot,
+ NULL,
+ &ReadyToBoot
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create events for PCH to do the task before ExitBootServices/LegacyBoot.
+ // It is guaranteed that only one of two events below will be signalled
+ //
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK,
+ PchOnExitBootServices,
+ NULL,
+ &ExitBootServicesEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = EfiCreateEventLegacyBootEx (
+ TPL_CALLBACK,
+ PchOnBootToOs,
+ NULL,
+ &LegacyBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Updates PCIe configuration in PCH Info Protocol.
+
+ @param[in,out] PchInfo Pointer to PCH info protocol instance to be updated
+**/
+VOID
+UpdatePcieConfigInfo (
+ IN OUT PCH_INFO_PROTOCOL *PchInfo
+ )
+{
+ EFI_STATUS Status;
+ PCH_SERIES PchSeries;
+ UINT32 StrapFuseCfg1;
+ UINT32 StrapFuseCfg5;
+ UINT32 StrapFuseCfg9;
+ UINT32 StrapFuseCfg13;
+ UINT32 StrapFuseCfg17;
+ UINT32 StrapFuseCfg21;
+
+ PchSeries = GetPchSeries ();
+
+ Status = PchSbiRpPciRead32 (
+ 0,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg1
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchSbiRpPciRead32 (
+ 4,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg5
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchSbiRpPciRead32 (
+ 8,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg9
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PchInfo->PcieControllerCfg1 = (UINT8) ((StrapFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ PchInfo->PcieControllerCfg2 = (UINT8) ((StrapFuseCfg5 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ PchInfo->PcieControllerCfg3 = (UINT8) ((StrapFuseCfg9 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+
+ if (PchSeries == PchH) {
+ Status = PchSbiRpPciRead32 (
+ 12,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg13
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PchSbiRpPciRead32 (
+ 16,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg17
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PchInfo->PcieControllerCfg4 = (UINT8) ((StrapFuseCfg13 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ PchInfo->PcieControllerCfg5 = (UINT8) ((StrapFuseCfg17 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+
+ if (GetPchGeneration () == KblPch) {
+ Status = PchSbiRpPciRead32 (
+ 20,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg21
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PchInfo->PcieControllerCfg6 = (UINT8) ((StrapFuseCfg21 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ }
+
+ }
+}
+
+/**
+ Stores PCIE Gen3 software equalization settings in bootscript to accelerate S3 resume
+**/
+VOID
+SavePcieGen3Eq (
+ VOID
+ )
+{
+ UINT8 RpIndex;
+ UINTN RpBase;
+ UINT8 EqMethod;
+ UINT32 Data32;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ for (RpIndex = 0; RpIndex < GetPchMaxPciePortNum (); ++RpIndex) {
+ RpBase = PchPcieBase (RpIndex);
+ //
+ // Before trying to save it, make sure software gen3 equalization did actually happen
+ //
+ if (MmioRead32 (RpBase) == 0xFFFFFFFF) {
+ continue;
+ }
+ if (GetMaxLinkSpeed (RpBase) < 3) {
+ continue;
+ }
+ EqMethod = mPchConfigHob->PcieRp.RootPort[RpIndex].Gen3EqPh3Method;
+ if (EqMethod != PchPcieEqDefault && EqMethod != PchPcieEqSoftware) {
+ continue;
+ }
+ //
+ // Can't check current link speed due to some nonconformant devices
+ // Instead we verify B_PCH_PCIE_EQCFG1_RTLEPCEB bit which together with policy check above
+ // guarantees that software gen3 eq was performed
+ //
+ if (!(MmioRead32 (RpBase + R_PCH_PCIE_EQCFG1) & B_PCH_PCIE_EQCFG1_RTLEPCEB)) {
+ continue;
+ }
+
+ //
+ // Restore PCIE Gen3 equalization coefficients
+ //
+ Data32 = MmioRead32 (RpBase + R_PCH_PCIE_RTPCL1);
+ S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_RTPCL1, 1, &Data32);
+ Data32 = MmioRead32 (RpBase + R_PCH_PCIE_RTPCL2);
+ S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_RTPCL2, 1, &Data32);
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCIE_EQCFG1_RTLEPCEB | B_PCH_PCIE_EQCFG1_RTPCOE;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_EQCFG1, &Data32Or, &Data32And);
+
+ //
+ // Perform link retrain.
+ //
+ Data32And = (UINT32) (~B_PCIE_LCTL2_TLS);
+ Data32Or = V_PCIE_LCTL2_TLS_GEN3;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_LCTL2, &Data32Or, &Data32And);
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCIE_EX_LCTL3_PE;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_EX_LCTL3, &Data32Or, &Data32And);
+ Data32Or = B_PCIE_LCTL_RL;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_LCTL, &Data32Or, &Data32And);
+ /// PCH BIOS Spec Section 8.15 Additional PCI Express* Programming Steps
+ /// Set "Link Speed Training Policy", Dxx:Fn + D4h[6] to 1.
+ /// Make sure this is after mod-PHY related programming is completed.
+ Data32Or = B_PCH_PCIE_MPC2_LSTP;
+ DEBUG ((DEBUG_WARN, "Gen3Eq S3MmioOr32 0x%08x\n", RpBase + R_PCH_PCIE_MPC2));
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_MPC2, &Data32Or, &Data32And);
+ }
+}
+
+/**
+ Initialize the PCH device according to the PCH Policy HOB
+ and install PCH info instance.
+**/
+VOID
+InitializePchDevice (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ PCH_INFO_PROTOCOL *PchInfo;
+ EFI_STATUS Status;
+ UINT32 PchPwrmBase;
+
+ Handle = NULL;
+
+ DEBUG ((DEBUG_INFO, "InitializePchDevice() Start\n"));
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ //
+ // Create the PCH Info protocol instance
+ //
+ PchInfo = AllocateZeroPool (sizeof (PCH_INFO_PROTOCOL));
+ if (PchInfo == NULL) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ PchInfo->Revision = PCH_INFO_PROTOCOL_REVISION;
+
+ UpdatePcieConfigInfo (PchInfo);
+
+ //
+ // Store PCIE Gen3 software equalization settings in bootscripts to save time on S3 resume
+ // This must happen before some rootports get hidden by RST remapping
+ //
+ SavePcieGen3Eq ();
+
+
+ //
+ // Configure root port function number mapping
+ // For UEFI bios, execute RPFN mapping after RST configuraion and before PCI enumeration.
+ //
+ Status = PchConfigureRpfnMapping ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Pch Emmc Tuning Protocol
+ //
+ if ((mPchConfigHob->Scs.ScsEmmcEnabled == TRUE) && (mPchConfigHob->Scs.ScsEmmcHs400Enabled == TRUE)) {
+ InstallPchEmmcTuningProtocol ();
+ }
+
+ //
+ // Install PCH info protocol on new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gPchInfoProtocolGuid,
+ PchInfo,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "InitializePchDevice() End\n"));
+}
+/**
+ <b>PchInit DXE Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchInit module is a DXE driver that initializes the Intel Platform Controller Hub
+ following the PCH BIOS specification and EDS requirements and recommendations. It consumes
+ the PCH_POLICY_HOB SI_POLICY_HOB for expected configurations per policy.
+ This is the standard EFI driver point that detects whether there is an supported PCH in
+ the system and if so, initializes the chipset.
+
+ - <b>Details</b>\n
+ This module is required for initializing the Intel Platform Controller Hub to
+ follow the PCH BIOS specification and EDS.
+ This includes some initialization sequences, enabling and disabling PCH devices,
+ configuring clock gating, RST PCIe Storage Remapping, SATA controller, ASPM of PCIE devices. Right before end of DXE,
+ it's responsible to lock down registers for security requirement.
+
+ - @pre
+ - PCH PCR base address configured
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+
+ - @result
+ - Publishes the @link _PCH_INFO_PROTOCOL PCH_INFO_PROTOCOL @endlink
+ - Publishes the @link _PCH_EMMC_TUNING_PROTOCOL PCH_EMMC_TUNING_PROTOCOL @endlink
+
+ - <b>References</b>\n
+ - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
+ - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink.
+
+ - <b>Integration Checklists</b>\n
+ - Verify prerequisites are met. Porting Recommendations.
+ - No modification of this module should be necessary
+ - Any modification of this module should follow the PCH BIOS Specification and EDS
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchInitEntryPointDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() Start\n"));
+
+ mImageHandle = ImageHandle;
+
+ PchInitEntryPointCommon ();
+
+ InitializePchDevice ();
+
+ Status = PchAcpiInit (ImageHandle);
+
+ CreateSerialIoHandles ();
+
+ PchRegisterNotifications ();
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() End\n"));
+
+ return Status;
+}
+
+/**
+ PCH initialization before ExitBootServices / LegacyBoot events
+ Useful for operations which must happen later than at EndOfPost event
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+PchOnBootToOs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ ///
+ /// Closed the event to avoid call twice
+ ///
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ ConfigureSerialIoAtBoot ();
+
+ return;
+}
+
+/**
+ PCH initialization on ExitBootService. This event is used if only ExitBootService is used
+ and not in legacy boot
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchOnExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ PchOnBootToOs (NULL, NULL);
+
+ PchUpdateNvsOnExitBootServices ();
+
+ return;
+}
+
+/**
+ PCH initialization before boot to OS
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+PchOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+#ifndef FSP_WRAPPER_FLAG
+ UINTN XhciMmioBase;
+ UINTN XhciPciMmBase;
+ UINT8 XhciPciCommand;
+ BOOLEAN XhciPdoRestartNeeded;
+#endif // FSP_WRAPPER_FLAG
+
+ DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() Start\n"));
+
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+#ifndef FSP_WRAPPER_FLAG
+ if (mPchConfigHob->Usb.DelayPdoProgramming == TRUE) {
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ // Check if xHCI has memory access
+ XhciPciCommand = MmioRead8 (XhciPciMmBase + PCI_COMMAND_OFFSET);
+
+ if ((XhciPciCommand & EFI_PCI_COMMAND_MEMORY_SPACE) == 0x0) {
+ DEBUG ((DEBUG_ERROR, "xHCI Controller isn't configured properly for PDO setting\n"));
+ } else {
+ // Getting base MMIO address for xHCI
+ XhciMmioBase = (
+ MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) |
+ ((UINTN) MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE_2) << N_PCH_XHCI_MEM_SHIFT)
+ ) & ((UINTN)~(B_PCH_XHCI_MEM_ALIGN_MASK));
+
+ XhciPdoRestartNeeded = UsbPdoProgramming (
+ XhciMmioBase,
+ mPchConfigHob->Usb.Usb2DisabledPorts,
+ mPchConfigHob->Usb.Usb3DisabledPorts
+ );
+ // If PDO registers are locked, reset platform to unlock them
+ if (XhciPdoRestartNeeded) {
+ gST->RuntimeServices->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "PDO register already programmed\n"));
+ }
+#endif // FSP_WRAPPER_FLAG
+
+ //
+ // Trigger an Iotrap SMI to config PCIE power management setting after PCI enumrate is done
+ //
+ if (mPcieIoTrapAddress != 0) {
+ IoWrite32 ((UINTN) mPcieIoTrapAddress, PciePmTrap);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() End\n"));
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf
new file mode 100644
index 0000000000..0242dcbe9a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf
@@ -0,0 +1,101 @@
+## @file
+# Component description file for Pch Initialization driver
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchInitDxe
+FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE823
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = PchInitEntryPointDxe
+
+
+[LibraryClasses]
+S3BootScriptLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchP2sbLib
+PchPcrLib
+PchInfoLib
+PchPciExpressHelpersLib
+UefiBootServicesTableLib
+DebugLib
+IoLib
+TimerLib
+HobLib
+BaseMemoryLib
+MemoryAllocationLib
+UefiLib
+DxeServicesTableLib
+UefiDriverEntryPoint
+UefiRuntimeServicesTableLib
+AslUpdateLib
+CpuPlatformLib
+GpioLib
+PchSerialIoLib
+PchHdaLib
+PchInitCommonLib
+ConfigBlockLib
+PchPsfLib
+PchPsfPrivateLib
+RstPrivateLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchInitDxe.c
+PchInit.h
+PchInit.c
+PchSata.c
+PchRstPcieStorage.c
+PchSerialIo.c
+PchSerialIoDxe.c
+PchHdaAcpi.c
+PchScs.c
+PchCio2Acpi.c
+PchAcpi.c
+
+
+[Protocols]
+gPchInfoProtocolGuid ## PRODUCES
+gPchNvsAreaProtocolGuid ## PRODUCES
+gPchEmmcTuningProtocolGuid ## PRODUCES
+gEfiPciIoProtocolGuid ## CONSUMES
+gEfiAcpiTableProtocolGuid ## CONSUMES
+gEfiBlockIoProtocolGuid ## CONSUMES
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+gPchPcieIoTrapProtocolGuid ## CONSUMES
+
+
+[Guids]
+gEfiEndOfDxeEventGroupGuid
+gEfiAcpiTableGuid
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+gPchPcieStorageDetectHobGuid ## 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/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf
new file mode 100644
index 0000000000..18feffd894
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf
@@ -0,0 +1,80 @@
+## @file
+# Component description file for Pch Initialization driver for FSP package
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010005
+BASE_NAME = PchInitDxe
+FILE_GUID = 5AA5031E-4CB6-43D4-B219-FE50FF5D116C
+MODULE_TYPE = PEIM
+VERSION_STRING = 1.0
+ENTRY_POINT = PchInitEntryPointFsp
+
+
+[LibraryClasses]
+PeimEntryPoint
+PchCycleDecodingLib
+PchPcieRpLib
+PchP2sbLib
+PchPcrLib
+PchInfoLib
+PchEspiLib
+PchPciExpressHelpersLib
+DebugLib
+IoLib
+TimerLib
+HobLib
+BaseMemoryLib
+MemoryAllocationLib
+CpuPlatformLib
+GpioLib
+PchSerialIoLib
+PchInitCommonLib
+S3BootScriptLib # NULL library
+ConfigBlockLib
+PchPsfLib
+PchPsfPrivateLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[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/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c
new file mode 100644
index 0000000000..9307b8fc4c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c
@@ -0,0 +1,169 @@
+/** @file
+ This is the FSP driver that initializes the Intel PCH.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInit.h"
+
+EFI_STATUS
+EFIAPI
+PchOnPciEnumCompleteFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+STATIC
+EFI_PEI_NOTIFY_DESCRIPTOR mPchOnPciEnumCompleteNotifyList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ PchOnPciEnumCompleteFsp
+ }
+};
+
+EFI_STATUS
+EFIAPI
+PchReadyToBootEventFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mReadyToBootNotifyList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEventReadyToBootGuid,
+ PchReadyToBootEventFsp
+ }
+};
+
+
+/**
+ <b>FSP PchInit Module Entry Point for FSP</b>\n
+
+ @param[in] FileHandle PEIM's file handle
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchInitEntryPointFsp (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() Start\n"));
+
+ PchInitEntryPointCommon ();
+
+ Status = PeiServicesNotifyPpi (mPchOnPciEnumCompleteNotifyList);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesNotifyPpi (mReadyToBootNotifyList);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() End\n"));
+
+ return Status;
+}
+
+/**
+ Fsp PCH initialization on PCI enumeration complete
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchOnPciEnumCompleteFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() Start\n"));
+
+ PchOnPciEnumCompleteCommon ();
+
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ FSP PCH Ready to boot event handler
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchReadyToBootEventFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ UINTN XhciMmioBase;
+ UINTN XhciPciMmBase;
+ UINT16 XhciPciCommand;
+ BOOLEAN XhciPdoRestartNeeded;
+
+ DEBUG ((DEBUG_INFO, "PchReadyToBootEventFsp() Start\n"));
+
+ // Check if USB PDO programming was skipped during PEI phase
+ if (mPchConfigHob->Usb.DelayPdoProgramming == TRUE) {
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ // Check if xHCI has memory access
+ XhciPciCommand = MmioRead16 (XhciPciMmBase + PCI_COMMAND_OFFSET);
+ if ((XhciPciCommand & EFI_PCI_COMMAND_MEMORY_SPACE) == 0x0) {
+ DEBUG ((DEBUG_ERROR, "xHCI Controller isn't configured properly\n"));
+ } else {
+ // Getting base MMIO address for xHCI
+ XhciMmioBase = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & (B_PCH_XHCI_MEM_ALIGN_MASK << N_PCH_XHCI_MEM_ALIGN);
+
+ XhciPdoRestartNeeded = UsbPdoProgramming (
+ XhciMmioBase,
+ mPchConfigHob->Usb.Usb2DisabledPorts,
+ mPchConfigHob->Usb.Usb3DisabledPorts
+ );
+ // If PDO registers are locked, reset platform to unlock them
+ if (XhciPdoRestartNeeded) {
+ (*PeiServices)->ResetSystem2 (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "PDO register already programmed\n"));
+ }
+
+ DEBUG ((DEBUG_INFO, "PchReadyToBootEventFsp() End\n"));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c
new file mode 100644
index 0000000000..801abf2602
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c
@@ -0,0 +1,286 @@
+/** @file
+ Configures the remapping for PCH Intel RST PCie Storage
+ In order to use this feature, Intel RST Driver is required
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInit.h"
+#include <Library/RstPrivateLib.h>
+#include <PchPcieStorageDetectHob.h>
+
+//
+// Variables below indicate the memory range to be allocated to the PCIe storage device BAR usage when it is HIDDEN,
+// thus it does not overlapped with the SGREG_BAR from the host perspective
+//
+#define RST_PCIE_STORAGE_MEMORY_START_RANGE PCH_PCR_BASE_ADDRESS
+#define RST_PCIE_STORAGE_MEMORY_END_RANGE (PCH_PCR_BASE_ADDRESS + PCH_PCR_MMIO_SIZE - 1)
+
+#define PCI_CARD_PM_CAP_ID 0x01
+#define PCI_CARD_MSIX_CAP_ID 0x11
+#define PCI_CARD_SATA_CAP_ID 0x12
+#define PCI_CARD_BAR_TOTAL 6
+#define PCI_CARD_LINK_SPEED_GEN1_GEN2 0
+#define PCI_CARD_LINK_SPEED_GEN3 1
+#define PCI_CARD_LINK_WIDTH_1 0
+#define PCI_CARD_LINK_WIDTH_2 1
+#define PCI_CARD_LINK_WIDTH_4 2
+#define PCI_CARD_REVISION 0x08
+#define PCI_CARD_BASE_ADDR0 0x10
+#define PCI_CARD_BASE_ADDR1 0x14
+#define PCI_CARD_BASE_ADDR5 0x24
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_RST_PCIE_STORAGE_DETECTION mRstPcieStorageDetection [PCH_MAX_RST_PCIE_STORAGE_CR];
+
+UINT32 PchRstPcieStorageCurrentMemoryRange = RST_PCIE_STORAGE_MEMORY_START_RANGE;
+
+
+/**
+ Function to perform dump for PCH_RST_PCIE_STORAGE_DETECTION
+
+ @param[in] Index Index for RST PCIe Storage Cycle Router Instance
+
+ @retval None
+**/
+VOID
+PchRstPcieStorageRemappingDump (
+ IN UINTN Index
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ DEBUG ((DEBUG_INFO, "PchRstPcieStorageRemappingDump() Started\n"));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].SupportRstPcieStoragRemapping = %x\n", Index, mRstPcieStorageDetection[Index].SupportRstPcieStoragRemapping));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].RootPortNum = %x\n", Index, mRstPcieStorageDetection[Index].RootPortNum));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].RootPortLane = %x\n", Index, mRstPcieStorageDetection[Index].RootPortLane));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].DeviceInterface = %x\n", Index, mRstPcieStorageDetection[Index].DeviceInterface));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].IsMsixSupported = %x\n", Index, mRstPcieStorageDetection[Index].IsMsixSupported));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].MsixStartingVector = %x\n", Index, mRstPcieStorageDetection[Index].MsixStartingVector));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].MsixEndingVector = %x\n", Index, mRstPcieStorageDetection[Index].MsixEndingVector));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointBarSize = %x\n", Index, mRstPcieStorageDetection[Index].EndPointBarSize));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixTableBar = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBar));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixTableBarValue = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBarValue));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixPbaBar = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBar));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixPbaBarValue = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBarValue));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointBcc = %x\n", Index, mRstPcieStorageDetection[Index].EndPointBcc));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointScc = %x\n", Index, mRstPcieStorageDetection[Index].EndPointScc));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointPi = %x\n", Index, mRstPcieStorageDetection[Index].EndPointPi));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.PmCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PmCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.PcieCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PcieCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.L1ssCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.L1ssCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointL1ssControl2 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl2));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointL1ssControl1 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl1));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.LtrCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.LtrCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointLtrData = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLtrData));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointLctlData16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLctlData16));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointDctlData16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctlData16));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointDctl2Data16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctl2Data16));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.RootPortDctl2Data16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.RootPortDctl2Data16));
+ DEBUG ((DEBUG_INFO, "PchRstPcieStorageRemappingDump() Ended\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Perform memory space allocation or free memory pool for AHCI BAR
+
+ @param[in] Operation True: Perform memory space allocation for AHCI BAR
+ False: Perform memory pool free for AHCI BAR
+ @param[in,out] MemBaseAddress The base memory address used by AHCI BAR
+**/
+VOID
+AbarMemorySpaceOperation (
+ IN BOOLEAN Operation,
+ IN OUT EFI_PHYSICAL_ADDRESS *MemBaseAddress
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINTN AhciBarAlignment;
+ UINTN AhciBarLength;
+
+ //
+ // Assign a 512k size memory space to the ABAR when NVM Remapping is enabled
+ //
+ AhciBarAlignment = N_PCH_SATA_AHCI_BAR_ALIGNMENT_512K; // 2^19: 512K Alignment
+ AhciBarLength = V_PCH_SATA_AHCI_BAR_LENGTH_512K; // 512K Length
+
+
+ if (Operation == TRUE) {
+ ///
+ /// If MemBaseAddress is not allocated yet, allocate the AHCI BAR
+ ///
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ BaseAddress = 0x0ffffffff;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ AhciBarAlignment,
+ AhciBarLength,
+ &BaseAddress,
+ mImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ *MemBaseAddress = BaseAddress;
+ } else {
+ ///
+ /// Else, free the GCD pool
+ ///
+ gDS->FreeMemorySpace (
+ *MemBaseAddress,
+ AhciBarLength
+ );
+ }
+}
+
+/**
+ Function to perform memory allocation for PCIe storage device that support unique BAR
+
+ @param[in] BarSize The BAR size required for memory allocation
+ @param[in,out] AllocAddr The Address that been allocated by this function
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Memory or storage is not enough
+**/
+EFI_STATUS
+PchRstPcieStorageMemAllocation (
+ IN UINT32 BarSize,
+ IN OUT UINT32 *AllocAddr
+ )
+{
+ if ((PchRstPcieStorageCurrentMemoryRange + BarSize) > RST_PCIE_STORAGE_MEMORY_END_RANGE) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if ((PchRstPcieStorageCurrentMemoryRange & (BarSize - 1)) != 0) {
+ *AllocAddr = (PchRstPcieStorageCurrentMemoryRange + BarSize) & ~(BarSize-1);
+ } else {
+ *AllocAddr = PchRstPcieStorageCurrentMemoryRange;
+ }
+
+ PchRstPcieStorageCurrentMemoryRange = *AllocAddr + BarSize;
+ return EFI_SUCCESS;
+}
+
+/**
+ Check and detect PCIe storage device per policies, and if existed, indicate if it should be subjected for remapping
+ Populate the mRstPcieStorageDetection structure along with it for later usages
+
+ @param[in, out] RemappingRequired Boolean value with TRUE indicates that RST PCIe Storage Remapping is required
+ @param[in] TempPciBusMin The temporary minimum Bus number for root port initialization
+ @param[in] SataRegBase SATA Register Base
+
+ @retval None
+**/
+VOID
+DetectPcieStorageDevices (
+ IN OUT BOOLEAN *RemappingRequired,
+ IN UINT8 TempPciBusMin,
+ IN UINTN SataRegBase
+ )
+{
+ EFI_STATUS Status;
+ PCH_SERIES PchSeries;
+ UINT8 DeviceInterface;
+ UINT32 PortNum;
+ UINTN PciRootPortRegBase;
+ UINTN RpDev;
+ UINTN RpFunc;
+ UINT8 RootPortLane;
+ PCIE_STORAGE_INFO_HOB *PcieStorageInfoHob;
+ VOID *Hob;
+ UINT32 CycleRouterNum;
+
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: DetectPcieStorageDevices Started\n"));
+
+ Hob = NULL;
+ Hob = GetFirstGuidHob (&gPchPcieStorageDetectHobGuid);
+ if (Hob != NULL) {
+ PcieStorageInfoHob = (PCIE_STORAGE_INFO_HOB *) GET_GUID_HOB_DATA (Hob);
+ } else {
+ return;
+ }
+
+ PchSeries = GetPchSeries ();
+
+ for (PortNum = 0; PortNum < GetPchMaxPciePortNum (); PortNum++) {
+
+ //
+ // Check Info hob for Cycle Router avaliable
+ // skip to next root port if Cr is not avaliable
+ //
+ CycleRouterNum = PcieStorageInfoHob->RstCycleRouterMap[PortNum / 4];
+ if (CycleRouterNum == RST_PCIE_STORAGE_CR_INVALID) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: cycle router not avaliable on Rp = %d\n", PortNum));
+ continue;
+ }
+
+ Status = GetPchPcieRpDevFun (PortNum, &RpDev, &RpFunc);
+ ASSERT_EFI_ERROR (Status);
+
+ PciRootPortRegBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDev, (UINT32) RpFunc);
+ RootPortLane = RstGetRpLaneOccupyMask (PortNum);
+
+
+ if (RootPortLane == 0) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: root port lane is not occupied\n"));
+ continue;
+ }
+
+ ///
+ /// Check if the RST PCIe Storage Cycle Router is enabled, continue to the next root port in the next x4 lane if it is disabled
+ ///
+ if (mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].Enable == 0) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: RST PCIe Storage Cycle Router %d is disabled\n", CycleRouterNum));
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: Proceed to root port in the next x4 lane (@ port %d)\n", PortNum + 1));
+ PortNum += 3 - (PortNum % 4);
+ continue;
+ }
+
+ ///
+ /// Check if the current root port is matching selected root port from policy, continue to next port if they are not matched
+ ///
+ if ((mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].RstPcieStoragePort != 0) &&
+ (mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].RstPcieStoragePort != PortNum + 1)) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: root port %d not matched with selected root port, proceed to next port\n", PortNum + 1));
+ continue;
+ }
+
+
+ // Read device programming interface from info hob
+ // if no device is present continue
+ if (PcieStorageInfoHob->PcieStorageLinkWidth[PortNum]) {
+ DeviceInterface = PcieStorageInfoHob->PcieStorageProgrammingInterface[PortNum];
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: Device present on RP# %d, PiInterface = %d\n", PortNum + 1, DeviceInterface));
+ } else {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: RP# %d no device present\n", PortNum + 1));
+ continue;
+ }
+
+
+ ///
+ /// Update the remapping detail for detected PCIe storage device, and move to the root port in the next x4 lane
+ ///
+ if ((DeviceInterface != RST_PCIE_STORAGE_INTERFACE_NONE)) {
+ mRstPcieStorageDetection[CycleRouterNum].SupportRstPcieStoragRemapping = TRUE;
+ mRstPcieStorageDetection[CycleRouterNum].RootPortNum = (UINT8) PortNum;
+ mRstPcieStorageDetection[CycleRouterNum].RootPortLane = RootPortLane;
+ mRstPcieStorageDetection[CycleRouterNum].DeviceInterface = DeviceInterface;
+ PortNum += 3 - (PortNum % 4);
+ *RemappingRequired = TRUE;
+ } else {
+ continue;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: DetectPcieStorageDevices() Ended\n"));
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
new file mode 100644
index 0000000000..d1f2948de6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
@@ -0,0 +1,125 @@
+/** @file
+ Perform related functions for PCH Sata in DXE phase
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PchInit.h>
+
+/**
+ Perform the remaining configuration on PCH SATA to perform device detection,
+ then set the SATA SPD and PxE corresponding, and set the Register Lock on PCH SATA
+
+ @retval None
+**/
+VOID
+ConfigurePchSataOnEndOfDxe (
+ VOID
+ )
+{
+ UINTN PciSataRegBase;
+ UINT16 SataPortsEnabled;
+ PCH_SERIES PchSeries;
+ UINT16 WordReg;
+ UINT32 DwordReg;
+ UINTN Index;
+
+ ///
+ /// 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 = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA);
+ PchSeries = GetPchSeries ();
+ SataPortsEnabled = 0;
+
+ if (MmioRead16 (PciSataRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+ if (PchSeries == PchLp) {
+ WordReg = MmioRead16 (PciSataRegBase + R_PCH_LP_SATA_PCS);
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ if ((mPchConfigHob->Sata.PortSettings[Index].HotPlug == TRUE) ||
+ (WordReg & (B_PCH_LP_SATA_PCS_P0P << Index)) ||
+ (mPchConfigHob->Sata.TestMode == TRUE) ||
+ (mPchConfigHob->Sata.PortSettings[Index].External == TRUE)) {
+ SataPortsEnabled |= (mPchConfigHob->Sata.PortSettings[Index].Enable << Index);
+ }
+ }
+
+ ///
+ /// Set MAP."Sata PortX Disable", SATA PCI offset 90h[10:8] to 1b if SATA Port 0/1/2 is disabled
+ ///
+ MmioOr16 (PciSataRegBase + R_PCH_LP_SATA_MAP, ((~SataPortsEnabled << N_PCH_LP_SATA_MAP_SPD) & (UINT16) B_PCH_LP_SATA_MAP_SPD));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (PciSataRegBase + R_PCH_LP_SATA_MAP),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_LP_SATA_MAP)
+ );
+
+ ///
+ /// Program PCS "Port X Enabled", SATA PCI offset 92h[2:0] = Port 0~2 Enabled bit as per SataPortsEnabled value.
+ ///
+ MmioOr16 (PciSataRegBase + R_PCH_LP_SATA_PCS, SataPortsEnabled);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (PciSataRegBase + R_PCH_LP_SATA_PCS),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_LP_SATA_PCS)
+ );
+ } else {
+ DwordReg = MmioRead32 (PciSataRegBase + R_PCH_H_SATA_PCS);
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ if ((mPchConfigHob->Sata.PortSettings[Index].HotPlug == TRUE) ||
+ (DwordReg & (B_PCH_H_SATA_PCS_P0P << Index)) ||
+ (mPchConfigHob->Sata.TestMode == TRUE) ||
+ (mPchConfigHob->Sata.PortSettings[Index].External == TRUE)) {
+ SataPortsEnabled |= (mPchConfigHob->Sata.PortSettings[Index].Enable << Index);
+ }
+ }
+
+ ///
+ /// Set MAP."Sata PortX Disable", SATA PCI offset 90h[23:16] to 1b if SATA Port 0/1/2/3/4/5/6/7 is disabled
+ ///
+ MmioOr32 (PciSataRegBase + R_PCH_H_SATA_MAP, ((~SataPortsEnabled << N_PCH_H_SATA_MAP_SPD) & (UINT32) B_PCH_H_SATA_MAP_SPD));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PciSataRegBase + R_PCH_H_SATA_MAP),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_H_SATA_MAP)
+ );
+
+ ///
+ /// Program PCS "Port X Enabled", SATA PCI offset 94h[7:0] = Port 0~7 Enabled bit as per SataPortsEnabled value.
+ ///
+ MmioOr16 (PciSataRegBase + R_PCH_H_SATA_PCS, SataPortsEnabled);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (PciSataRegBase + R_PCH_H_SATA_PCS),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_H_SATA_PCS)
+ );
+ }
+
+ ///
+ /// Step 14
+ /// Program SATA PCI offset 9Ch [31] to 1b
+ ///
+ MmioOr32 ((UINTN) (PciSataRegBase + R_PCH_SATA_SATAGC), BIT31);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PciSataRegBase + R_PCH_SATA_SATAGC),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_SATA_SATAGC)
+ );
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c
new file mode 100644
index 0000000000..34227826b4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c
@@ -0,0 +1,1869 @@
+/** @file
+ Initializes PCH Storage and Communications Subsystem Controllers.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PchInit.h>
+
+//
+// HS400 Tuning Definitions
+//
+#define RX_STROBE_DLL1_TAP_MAX_RANGE 39
+#define RX_STROBE_DLL1_TAP_MIN_RANGE 0
+#define RX_STROBE_DLL1_TAP_MIN_MEPT 5
+#define RX_STROBE_DLL1_TAP_MAX_MEPT 16
+#define TX_DATA_DLL_TAP_MAX_RANGE 79
+#define TX_DATA_DLL_TAP_MIN_RANGE 0
+#define TX_DATA_DLL_TAP_MIN_MEPT 4
+#define TX_DATA_DLL_TAP_MAX_MEPT 22
+
+//
+// Command Definitions
+//
+#define CMD6 6
+#define CMD8 8
+#define CMD13 13
+#define CMD31 31
+#define SWITCH CMD6
+#define SEND_EXT_CSD CMD8
+#define SEND_STATUS CMD13
+#define SEND_WRITE_PROT_TYPE CMD31
+#define WRITE_BYTE_MODE 3
+#define BLOCK_LENGTH 512
+#define TIMEOUT_COMMAND 100
+#define TIMEOUT_DATA 5000
+#define HS_TIMING_INDEX 185
+#define BUS_WIDTH_INDEX 183
+
+//
+// Card Status Definitions
+//
+#define SWITCH_ERROR BIT7
+#define ERASE_RESET BIT13
+#define WP_ERASE_SKIP BIT15
+#define CID_CSD_OVERWRITE BIT16
+#define ERROR BIT19
+#define CC_ERROR BIT20
+#define CARD_ECC_FAILED BIT21
+#define ILLEGAL_COMMAND BIT22
+#define COM_CRC_ERROR BIT23
+#define LOCK_UNLOCK_FAILED BIT24
+#define CARD_IS_LOCKED BIT25
+#define WP_VIOLATION BIT26
+#define ERASE_PARAM BIT27
+#define ERASE_SEQ_ERROR BIT28
+#define BLOCK_LEN_ERROR BIT29
+#define ADDRESS_MISALIGN BIT30
+#define ADDRESS_OUT_OF_RANGE BIT31
+
+typedef enum {
+ Hs200 = 0,
+ Hs400,
+ DDR50,
+ SDR25
+} EMMC_MODE;
+
+typedef enum {
+ RxDll1 = 0,
+ RxDll2
+} RX_STROBE_DLL_REG;
+
+typedef enum {
+ NotAvailable = 0,
+ Passed,
+ Failed
+} BLOCK_READ_WRITE_STATUS;
+
+typedef enum {
+ ResponseNo = 0,
+ ResponseR1,
+ ResponseR1b,
+ ResponseR2,
+ ResponseR3,
+ ResponseR4,
+ ResponseR5,
+ ResponseR5b,
+ ResponseR6,
+ ResponseR7
+} RESPONSE_TYPE;
+
+typedef enum {
+ NoData = 0,
+ InData,
+ OutData
+} TRANSFER_TYPE;
+
+typedef struct {
+ UINT32 CmdSet: 3;
+ UINT32 Reserved0: 5;
+ UINT32 Value: 8;
+ UINT32 Index: 8;
+ UINT32 Access: 2;
+ UINT32 Reserved1: 6;
+} SWITCH_ARGUMENT;
+
+//
+// PCH_EMMC_TUNING PROTOCOL Global Variable
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_EMMC_TUNING_PROTOCOL PchEmmcTuningProtocol = {
+ ConfigureEmmcHs400Mode
+};
+
+#define EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER 5
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 EmmcWorstCasePattern[] =
+{
+0x60FEFE00, 0xEDFF10FE, 0x60FEFE00, 0xEDFF10FE, 0xDE08216A, 0xE25F20DF, 0xDE08216A, 0xE25F20DF, // spt_a0_sandisk_50ohm
+0xFF00CFFF, 0x1014B5CF, 0xFF00CFFF, 0x1014B5CF, 0x225F25DF, 0x20DFDE61, 0x225F25DF, 0x20DFDE61, // spt_a0_sandisk_40ohm
+0xEFE770BD, 0x4AFF0000, 0xEFE770BD, 0x4AFF0000, 0x7B84FF5B, 0x5B655B0E, 0x7B84FF5B, 0x5B655B0E, // spt_a0_hynix_50ohm
+0x7B93D620, 0xDFFF00E8, 0x7B93D620, 0xDFFF00E8, 0x3DC2FF3D, 0x38EA7DF3, 0x3DC2FF3D, 0x38EA7DF3, // spt_a0_hynix_40ohm
+0x50127FAC, 0x4400FD00, 0x50127FAC, 0x4400FD00, 0x7887FF78, 0x109A394F, 0x7887FF78, 0x109A394F, // spt_a0_hynix_33ohm
+0x50F20DBF, 0x3832CDFD, 0x50F20DBF, 0x3832CDFD, 0xFB04D720, 0xE69DC704, 0xFB04D720, 0xE69DC704, // spt_a0_samsung19nm_33ohm
+0x40EFFF00, 0x40FFFF00, 0x40EFFF00, 0x40FFFF00, 0xE85F20DF, 0x20DF003F, 0xE85F20DF, 0x20DF003F, // spt_a0_toshiba_50ohm
+0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0x20DFA0FF, 0x58DB20DF, 0x20DFA0FF, 0x58DB20DF, // spt_a0_toshiba_40ohm
+0x50FF0008, 0x7E10FFFF, 0x50FF0008, 0x7E10FFFF, 0x3B8F7A85, 0xFF7A5AFF, 0x3B8F7A85, 0xFF7A5AFF, // spt_b0_hynix_40ohm
+0x8A7575FF, 0x9ACA7F54, 0x8A7575FF, 0x9ACA7F54, 0xDF649B92, 0x7B24AFA0, 0xDF649B92, 0x7B24AFA0, // spt_b0_samsung16nm_50ohm
+0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xDAD6EF50, 0x6B1C6B25, 0xDAD6EF50, 0x6B1C6B25, // spt_b0_samsung16nm_40ohm
+0x7f52ff02, 0xff02ff02, 0x7f52ff02, 0xff02ff02, 0x72bc63a5, 0x679afa9d, 0x72bc63a5, 0x679afa9d, // spt_b0_samsung16nm_33ohm
+
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, // baseline_pattern_8
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 EmmcWorstCasePatternSize = sizeof (EmmcWorstCasePattern);
+
+
+
+/**
+ Set max clock frequency of the host, the actual frequency may not be the same
+ as MaxFrequency. It depends on the max frequency the host can support, divider,
+ and host speed mode.
+
+ @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL
+ @param[in] MaxFrequency Max frequency in HZ
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT The timeout time expired.
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN UINTN EmmcBaseAddress,
+ IN UINT32 MaxFrequency
+ )
+{
+ UINT16 Data16;
+ UINT32 Frequency;
+ UINT32 Divider = 0;
+ UINT32 TimeOutCount;
+ UINT32 CurrentClockInKHz;
+
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: BaseClockInMHz = %d \n", 200));
+
+ Frequency = (200 * 1000 * 1000) / MaxFrequency;
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: FrequencyInHz = %d \n", Frequency));
+
+ if ((200 * 1000 * 1000 % MaxFrequency) != 0) {
+ Frequency += 1;
+ }
+
+ Divider = 1;
+ while (Frequency > Divider) {
+ Divider = Divider * 2;
+ }
+ if (Divider >= 0x400) {
+ Divider = 0x200;
+ }
+ Divider = Divider >> 1;
+
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: after shift: Base Clock Divider = 0x%x \n", Divider));
+
+ CurrentClockInKHz = (200 * 1000);
+ if (Divider != 0) {
+ CurrentClockInKHz = CurrentClockInKHz / (Divider * 2);
+ }
+ //
+ //Set frequency
+ // Bit[15:8] SDCLK Frequency Select at offset 2Ch
+ // 80h - base clock divided by 256
+ // 40h - base clock divided by 128
+ // 20h - base clock divided by 64
+ // 10h - base clock divided by 32
+ // 08h - base clock divided by 16
+ // 04h - base clock divided by 8
+ // 02h - base clock divided by 4
+ // 01h - base clock divided by 2
+ // 00h - Highest Frequency the target support (10MHz-63MHz)
+ //
+ // Bit [07:06] are assigned to bit 09-08 of clock divider in SDCLK Frequency Select on SD controller 3.0
+ //
+
+ Data16 = (UINT16) ((Divider & 0xFF) << 8 | (((Divider & 0xFF00) >> 8) << 6));
+
+ DEBUG ((DEBUG_INFO,
+ "SetClockFrequency: base=%dMHz, clkctl=0x%04x, f=%dKHz\n",
+ 200,
+ Data16,
+ CurrentClockInKHz
+ ));
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: set MMIO_CLKCTL value = 0x%x \n", Data16));
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, Data16);
+ Data16 |= BIT0;
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, Data16);
+ TimeOutCount = 1000;
+ do {
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL);
+ MicroSecondDelay (100);
+ TimeOutCount--;
+ if (TimeOutCount == 0) {
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: Timeout\n"));
+ return EFI_TIMEOUT;
+ }
+ } while ((Data16 & BIT1) != BIT1);
+
+ Data16 |= BIT2;
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, Data16);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Error Reason from Host
+
+ @param[in] CommandIndex Command Index which return error
+ @param[in] ErrorCode Command Error Code
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT Command Timeout Error
+ @retval EFI_TIMEOUT Data Timeout Error
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+ @retval EFI_DEVICE_ERROR Command End Bit Error
+ Command Index Error
+ Data End Bit Error
+ Current Limit Error
+ Auto CMD12 Error
+ ADMA Error
+**/
+STATIC
+EFI_STATUS
+EmmcGetErrorReason (
+ IN UINT16 CommandIndex,
+ IN UINT16 ErrorCode
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_ERROR, "[%2d] -- ", CommandIndex));
+
+ if (ErrorCode & BIT0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((DEBUG_ERROR, "Command Timeout Error\n"));
+ }
+
+ if (ErrorCode & BIT1) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((DEBUG_ERROR, "Command CRC Error\n"));
+ }
+
+ if (ErrorCode & BIT2) {
+ DEBUG ((DEBUG_ERROR, "Command End Bit Error\n"));
+ }
+
+ if (ErrorCode & BIT3) {
+ DEBUG ((DEBUG_ERROR, "Command Index Error\n"));
+ }
+
+ return Status;
+}
+
+/**
+ Reset the host CMD and DATA Line
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT The timeout time expired.
+**/
+EFI_STATUS
+EmmcReset (
+ IN UINTN EmmcBaseAddress
+ )
+{
+ UINT8 Data8;
+ UINT8 ResetType;
+ UINT16 SaveClkCtl;
+ UINT32 Data;
+ UINT32 TimeOutCount;
+
+ ResetType = (B_PCH_SCS_DEV_MEM_SWRST_CMDLINE | B_PCH_SCS_DEV_MEM_SWRST_DATALINE);
+
+ //
+ // To improve eMMC stability, we zero the R_PCH_SCS_DEV_MEM_CLKCTL register and
+ // stall for 50 microsecond before reseting the controller. We
+ // restore the register setting following the reset operation.
+ //
+ SaveClkCtl = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL);
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, 0);
+ MicroSecondDelay (50);
+ //
+ // Reset the SD host controller
+ //
+ MmioWrite8 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_SWRST, ResetType);
+
+ Data = 0;
+ TimeOutCount = 1000; // 1 second timeout
+ do {
+ MicroSecondDelay (1 * 1000);
+
+ TimeOutCount --;
+
+ Data8 = MmioRead8 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_SWRST);
+ if ((Data8 & ResetType) == 0) {
+ break;
+ }
+ } while (TimeOutCount > 0);
+
+ //
+ // We now restore the R_PCH_SCS_DEV_MEM_CLKCTL register which we set to 0 above.
+ //
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, SaveClkCtl);
+
+ if (TimeOutCount == 0) {
+ DEBUG ((DEBUG_ERROR, "EmmcReset: Time out \n"));
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check card status, print the DEBUG info and check the error
+
+ @param[in] CardStatus Status got from card status register
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.
+ @retval EFI_DEVICE_ERROR Device failed during operation
+**/
+EFI_STATUS
+EmmcCheckCardStatus (
+ IN UINT32 CardStatus
+ )
+{
+
+ EFI_STATUS Status;
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_ERROR, "CardStatus:"));
+
+ if (CardStatus & ADDRESS_OUT_OF_RANGE) {
+ DEBUG ((DEBUG_ERROR, " ADDRESS_OUT_OF_RANGE"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ADDRESS_MISALIGN) {
+ DEBUG ((DEBUG_ERROR, " ADDRESS_MISALIGN"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & BLOCK_LEN_ERROR) {
+ DEBUG ((DEBUG_ERROR, " BLOCK_LEN_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERASE_SEQ_ERROR) {
+ DEBUG ((DEBUG_ERROR, " ERASE_SEQ_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERASE_PARAM) {
+ DEBUG ((DEBUG_ERROR, " ERASE_PARAM"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & WP_VIOLATION) {
+ DEBUG ((DEBUG_ERROR, " WP_VIOLATION"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CARD_IS_LOCKED) {
+ DEBUG ((DEBUG_ERROR, " CARD_IS_LOCKED"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & LOCK_UNLOCK_FAILED) {
+ DEBUG ((DEBUG_ERROR, " LOCK_UNLOCK_FAILED"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & COM_CRC_ERROR) {
+ DEBUG ((DEBUG_ERROR, " COM_CRC_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ILLEGAL_COMMAND) {
+ DEBUG ((DEBUG_ERROR, " ILLEGAL_COMMAND"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CARD_ECC_FAILED) {
+ DEBUG ((DEBUG_ERROR, " CARD_ECC_FAILED"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CC_ERROR) {
+ DEBUG ((DEBUG_ERROR, " CC_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERROR) {
+ DEBUG ((DEBUG_ERROR, " ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CID_CSD_OVERWRITE) {
+ DEBUG ((DEBUG_ERROR, " CID_CSD_OVERWRITE"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & WP_ERASE_SKIP) {
+ DEBUG ((DEBUG_ERROR, " WP_ERASE_SKIP"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERASE_RESET) {
+ DEBUG ((DEBUG_ERROR, " ERASE_RESET"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & SWITCH_ERROR) {
+ DEBUG ((DEBUG_ERROR, " SWITCH_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_ERROR, " \n"));
+
+ return Status;
+}
+/**
+ The main function used to send the command to the card inserted into the SD/MMC host
+ slot. It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData.
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_OUT_OF_RESOURCES A resource has run out.
+ @retval EFI_TIMEOUT The timeout time expired.
+ @retval EFI_DEVICE_ERROR The physical device reported an error while attempting the operation
+**/
+EFI_STATUS
+SendCommand (
+ IN UINTN EmmcBaseAddress,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResponseDataCount;
+ UINT16 Data16;
+ UINT32 Data32;
+ UINT64 Data64;
+ UINT32 BlockLength;
+ UINT32 Index;
+ BOOLEAN CommandCompleted;
+ BOOLEAN BufferReadReady;
+ INT32 Timeout;
+
+ Status = EFI_SUCCESS;
+ BlockLength = BLOCK_LENGTH;
+
+ if (Buffer != NULL && DataType == NoData) {
+ Status = EFI_INVALID_PARAMETER;
+ return Status;
+ }
+
+ //
+ // Check CMD INHIBIT and DATA INHIBIT before send command
+ //
+ Timeout = 1000;
+ do {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_PSTATE);
+ MicroSecondDelay (100);
+ } while ((Timeout-- > 0) && (Data32 & BIT0));
+
+ Timeout = 1000;
+ do {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_PSTATE);
+ MicroSecondDelay (100);
+ } while ((Timeout-- > 0) && (Data32 & BIT1));
+
+
+ //
+ // Enable Interrupts
+ //
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTEN, B_PCH_SCS_DEV_MEM_NINTEN_MASK);
+
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTEN, B_PCH_SCS_DEV_MEM_ERINTEN_MASK);
+
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSIGNEN, B_PCH_SCS_DEV_MEM_NINTSIGNEN_MASK);
+
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTSIGNEN, B_PCH_SCS_DEV_MEM_ERINTSIGNEN_MASK);
+
+ //
+ // Clear status bits
+ //
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_CLEAR_MASK);
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTSTS, B_PCH_SCS_DEV_MEM_ERINTSTS_CLEAR_MASK);
+
+ if (Buffer != NULL) {
+ Data16 = 0;
+ if (BufferSize <= BlockLength) {
+ Data16 |= BufferSize;
+ } else {
+ Data16 |= BlockLength;
+ }
+ } else {
+ Data16 = 0;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_BLKSZ, Data16);
+
+ if (Buffer != NULL) {
+ if (BufferSize <= BlockLength) {
+ Data16 = 1;
+ } else {
+ Data16 = (UINT16) (BufferSize / BlockLength);
+ }
+ } else {
+ Data16 = 0;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_BLKCNT, Data16);
+
+ //
+ // Argument
+ //
+ MmioWrite32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CMDARG, Argument);
+
+ //
+ // Transfer Mode
+ //
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_XFRMODE);
+
+ //
+ // Data Transfer Direction Select
+ //
+ Data16 = 0;
+ if (DataType == InData) {
+ Data16 |= B_PCH_SCS_DEV_MEM_XFRMODE_DATA_TRANS_DIR;
+ }
+
+ if (CommandIndex == SEND_EXT_CSD) {
+ Data16 |= B_PCH_SCS_DEV_MEM_XFRMODE_BLKCNT_EN;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_XFRMODE, Data16);
+ //
+ //Command
+ //
+ //ResponseTypeSelect IndexCheck CRCCheck ResponseType
+ // 00 0 0 NoResponse
+ // 01 0 1 R2
+ // 10 0 0 R3, R4
+ // 10 1 1 R1, R5, R6, R7
+ // 11 1 1 R1b, R5b
+ //
+ switch (ResponseType) {
+ case ResponseNo:
+ Data16 = (CommandIndex << 8);
+ ResponseDataCount = 0;
+ break;
+
+ case ResponseR1:
+ case ResponseR5:
+ case ResponseR6:
+ case ResponseR7:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48 |
+ B_PCH_SCS_DEV_MEM_SDCMD_CMD_INDEX_CHECK_EN | B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR1b:
+ case ResponseR5b:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48_CHK |
+ B_PCH_SCS_DEV_MEM_SDCMD_CMD_INDEX_CHECK_EN | B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR2:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP136 |
+ B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN;
+ ResponseDataCount = 4;
+ break;
+
+ case ResponseR3:
+ case ResponseR4:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48;
+ ResponseDataCount = 1;
+ break;
+
+ default:
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ return Status;
+ }
+
+ if (DataType != NoData) {
+ Data16 |= B_PCH_SCS_DEV_MEM_SDCMD_DATA_PRESENT_SEL;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_SDCMD, Data16);
+ CommandCompleted = FALSE;
+ BufferReadReady = FALSE;
+ TimeOut = 1000;
+ do {
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTSTS);
+ if ((Data16 & B_PCH_SCS_DEV_MEM_ERINTSTS_MASK) != 0) {
+ Status = EmmcGetErrorReason (CommandIndex, Data16);
+ return Status;
+ }
+
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS) & 0x1ff;
+ if (Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE) {
+ //
+ // Command completed
+ //
+ CommandCompleted = TRUE;
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE);
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS);
+ if ((DataType == NoData) & (ResponseType != ResponseR1b)) {
+ break;
+ }
+ }
+
+ if ((CommandCompleted) && (ResponseType == ResponseR1b)) {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_PSTATE);
+ if (Data32 & B_PCH_SCS_DEV_MEM_PSTATE_DAT0) {
+ break;
+ }
+ }
+
+ if ((CommandCompleted) && (Buffer!= NULL)) {
+ if (!(Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE)) {
+
+ if (Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR) {
+ BufferReadReady = TRUE;
+ MmioOr16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR);
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS);
+ }
+
+ if (BufferReadReady) {
+ if (!(Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR)) {
+ for (Index = 0; Index < BufferSize; Index = Index + 4) {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_BUFDATAPORT);
+ if ((Index + 4) < BufferSize) {
+ CopyMem ((Buffer + Index), &Data32, 4);
+ } else {
+ CopyMem ((Buffer + Index), &Data32, (BufferSize - Index));
+ }
+ }
+ }
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS);
+ }
+
+ if (Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_TRANSFER_COMPLETE) {
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_TRANSFER_COMPLETE);
+ break;
+ }
+ }
+ }
+ MicroSecondDelay (1*1000);
+
+ TimeOut --;
+
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ return Status;
+ }
+
+ if (ResponseData != NULL) {
+ UINT32 *ResDataPtr = NULL;
+
+ ResDataPtr = ResponseData;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ *ResDataPtr = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RESP + Index * 4);
+ ResDataPtr++;
+ }
+
+ if (ResponseType == ResponseR2) {
+ //
+ // Adjustment for R2 response
+ //
+ Data32 = 1;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ Data64 = LShiftU64 (*ResponseData, 8);
+ *ResponseData = (UINT32) ((Data64 & 0xFFFFFFFF) | Data32);
+ Data32 = (UINT32) RShiftU64 (Data64, 32);
+ ResponseData++;
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ This main function is to send command to Emmc
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_OUT_OF_RESOURCES A resource has run out.
+ @retval EFI_TIMEOUT The timeout time expired.
+ @retval EFI_DEVICE_ERROR The physical device reported an error while attempting the operation
+**/
+EFI_STATUS
+EmmcSendCommand (
+ IN UINTN EmmcBaseAddress,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SendCommand (
+ EmmcBaseAddress,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ ASSERT (ResponseData != NULL);
+ Status = EmmcCheckCardStatus (*ResponseData);
+ if (EFI_ERROR (Status)) {
+ EmmcReset (EmmcBaseAddress);
+ }
+ }
+ } else {
+ //
+ // Reset Host Controller CMD and DATA
+ //
+ EmmcReset (EmmcBaseAddress);
+ }
+
+ return Status;
+}
+/**
+ Set Tx Data Delay Control 1
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] Value Value (0 - 79)
+
+ @retval VOID
+**/
+VOID
+EmmcSetTxDllCtrl1 (
+ IN UINTN EmmcBaseAddress,
+ IN UINT8 Value
+ )
+{
+ MmioAndThenOr8 (EmmcBaseAddress + (R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1 + 1), 0, Value);
+}
+
+/**
+ Set Rx Strobe Delay Control DLL1 for HS400
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] RxDll To program RxDll1 or RxDll2 register
+ @param[in] Value Value (0 - 39)
+
+ @retval VOID
+**/
+VOID
+EmmcSetRxDllCtrl (
+ IN UINTN EmmcBaseAddress,
+ IN UINT8 RxDll,
+ IN UINT8 Value
+ )
+{
+ if (RxDll == RxDll1) {
+ MmioAndThenOr8 (EmmcBaseAddress + (R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL + 1), 0, Value);
+ } else {
+ MmioAndThenOr8 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL, 0, Value);
+ }
+}
+
+/**
+ Disable eMMC Host HS400 Support
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+
+ @retval N/A
+**/
+VOID
+EmmcHostHs400Disabled (
+ IN UINTN EmmcBaseAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode()::EmmcHostHs400Disabled()\n"));
+ MmioAnd32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1, (UINT32) ~B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_HS400);
+}
+/**
+ Set Host Mode
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] Mode Set Host Mode, 0: HS200, 1: HS400
+
+ @retval N/A
+**/
+VOID
+EmmcSetHostMode (
+ IN UINTN EmmcBaseAddress,
+ IN UINT32 Mode
+ )
+{
+ UINT16 ModeSet;
+ UINT32 HostCapabilities;
+
+ ModeSet = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_HOST_CTL2);
+ HostCapabilities = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CAP2);
+
+ ModeSet &= ~B_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_MASK;
+ if ((Mode == Hs200) && (HostCapabilities & B_PCH_SCS_DEV_MEM_CAP2_SDR104_SUPPORT)) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR104;
+ } else if ((Mode == Hs400) && (HostCapabilities & B_PCH_SCS_DEV_MEM_CAP2_HS400_SUPPORT)) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_HS400;
+ } else if (Mode == DDR50) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_DDR50;
+ } else if (Mode == SDR25) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR25;
+ }
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode(): SetHostDdrMode = 0x%x\n", ModeSet));
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_HOST_CTL2, ModeSet);
+}
+
+/**
+ To select eMMC card operating mode HS200/HS400
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] EmmcMode To select HS200 or HS400 mode
+
+ @retval EFI_SUCCESS Emmc Mode Select successful.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+**/
+EFI_STATUS
+EmmcModeSelection (
+ IN EMMC_INFO *EmmcInfo,
+ IN UINTN EmmcBaseAddress,
+ IN EMMC_MODE EmmcMode
+ )
+{
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT32 CardStatus;
+ UINT32 HsTimingValue;
+ UINT32 BusWidthValue;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode()::EmmcModeSelection() Start\n"));
+
+ if (EmmcMode == Hs200) {
+ HsTimingValue = 0x02;
+ BusWidthValue = EmmcInfo->HS200BusWidth;
+ DEBUG ((DEBUG_INFO, "HS200 Driver Strength: 50 Ohm\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "HS400 Driver Strength: "));
+ switch (mPchConfigHob->Scs.ScsEmmcHs400DriverStrength) {
+ case DriverStrength33Ohm:
+ HsTimingValue = 0x13;
+ DEBUG ((DEBUG_INFO, "33 Ohm\n"));
+ break;
+ case DriverStrength40Ohm:
+ HsTimingValue = 0x43;
+ DEBUG ((DEBUG_INFO, "40 Ohm\n"));
+ break;
+ case DriverStrength50Ohm:
+ HsTimingValue = 0x03;
+ DEBUG ((DEBUG_INFO, "50 Ohm\n"));
+ break;
+ default:
+ HsTimingValue = 0x13;
+ DEBUG ((DEBUG_INFO, "default - 33 Ohm\n"));
+ }
+
+ BusWidthValue = 6;
+ }
+ SetClockFrequency (EmmcBaseAddress, (50 * 1000 * 1000)); // Set 50MHz
+ //
+ // 1. Set HS_TIMING to 0x01 for High Speed interface timing. This is required prior DDR 8 bit bus width setting (CMD6)
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = 1;
+ SwitchArgument.Index = HS_TIMING_INDEX;
+ SwitchArgument.Access = WRITE_BYTE_MODE;
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ &CardStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EmmcSetHostMode (EmmcBaseAddress, SDR25);
+
+ //
+ // 2. Set desired bus width to DDR 8 bit CMD6
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = BusWidthValue;
+ SwitchArgument.Index = BUS_WIDTH_INDEX;
+ SwitchArgument.Access = WRITE_BYTE_MODE;
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ &CardStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EmmcSetHostMode (EmmcBaseAddress, DDR50);
+
+ //
+ // 3. Set HS400 bit and Driver Strentgh value in HS_TIMING (CMD6)
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = HsTimingValue;
+ SwitchArgument.Index = HS_TIMING_INDEX;
+ SwitchArgument.Access = WRITE_BYTE_MODE;
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ &CardStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (EmmcMode == Hs200) {
+ DEBUG ((DEBUG_INFO, "Set eMMC Mode: HS200\n"));
+ EmmcSetHostMode (EmmcBaseAddress, Hs200);
+ } else {
+ DEBUG ((DEBUG_INFO, "Set eMMC Mode: HS400\n"));
+ EmmcSetHostMode (EmmcBaseAddress, Hs400);
+ }
+ SetClockFrequency (EmmcBaseAddress, (200 * 1000 * 1000)); // Set 200MHz
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode()::EmmcModeSelection() End\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Prints worst case pattern used for HS400 taining
+
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] TuningPattern Data buffer containg pattern for training
+ @param[in] TuningPatternSize Size of the buffer with pattern
+
+ @retval N/A
+**/
+VOID
+EmmcPrintHs400TuningPattern (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINT8 *TuningPattern,
+ IN UINT32 TuningPatternSize
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINT32 Index;
+
+ DEBUG ((DEBUG_VERBOSE, "--------------- TUNING PATTERN ----------------\n"));
+ DEBUG ((DEBUG_VERBOSE, "BlockIo->Media->MediaId = 0x%08x\n", BlockIo->Media->MediaId));
+ DEBUG ((DEBUG_VERBOSE, "BlockIo->Media->BlockSize = 0x%08x\n", BlockIo->Media->BlockSize));
+ DEBUG ((DEBUG_VERBOSE, "Tuning Pattern Size = 0x%08x\n", TuningPatternSize));
+ for (Index = 0; Index < TuningPatternSize; Index++) {
+ if (Index % 16 == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+ if (Index % (BlockIo->Media->BlockSize) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "-------------------- BLOCK --------------------\n"));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02x ", TuningPattern[Index]));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n-----------------------------------------------\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Writes worst case pattern used for HS400 taining
+
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] TuningPattern Data buffer containg pattern for training
+ @param[in] TuningPatternSize Size of the buffer with pattern
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+**/
+EFI_STATUS
+EmmcWriteHs400TuningPattern (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress,
+ IN UINT8 *TuningPattern
+ )
+{
+ UINT8 *Buffer;
+ UINT32 Index;
+ UINT32 TuningPatternSize;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ TuningPatternSize = BlockIo->Media->BlockSize * EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER;
+
+ DEBUG ((DEBUG_INFO, "EmmcWriteHs400TuningPattern() Start\n"));
+
+ Buffer = (VOID *) AllocateZeroPool (TuningPatternSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ for (Index = 0; Index < EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER; Index++){
+ CopyMem (Buffer + (Index * BlockIo->Media->BlockSize), TuningPattern, BlockIo->Media->BlockSize);
+ }
+
+ Status = BlockIo->WriteBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcWriteHs400TuningPattern: Multiple Blocks Write at HS200 Mode Failed!\n"));
+ goto Exit;
+ }
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcWriteHs400TuningPattern() End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ To perform HS400 Rx Data Path Training
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in/out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EmmcRxHs400Tuning (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress,
+ IN OUT EMMC_TUNING_DATA *EmmcTuningData
+ )
+{
+ UINT8 *Buffer;
+ UINT8 DllCount;
+ UINT8 DllMax;
+ UINT8 DllMin;
+ UINT8 Smin;
+ UINT8 Smax;
+ UINT8 Sopt;
+ EFI_STATUS Status;
+ EFI_STATUS ModeStatus;
+ BLOCK_READ_WRITE_STATUS FirstRead;
+ UINT32 TuningPatternSize;
+
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning() Start\n"));
+
+ Status = EFI_SUCCESS;
+ ModeStatus = EFI_SUCCESS;
+
+ Smin = RX_STROBE_DLL1_TAP_MIN_MEPT;
+ Smax = RX_STROBE_DLL1_TAP_MAX_MEPT;
+ TuningPatternSize = BlockIo->Media->BlockSize * EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER;
+
+ Buffer = (VOID *) AllocateZeroPool (TuningPatternSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // 1. Read Tuning Block
+ //
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcRxHs400Tuning: Tuning Blocks Read at HS200 Mode Failed!\n"));
+ goto Exit;
+ }
+
+ DEBUG_CODE ( EmmcPrintHs400TuningPattern (BlockIo, Buffer, TuningPatternSize); );
+
+ //
+ // 2. Move to HS400 Mode
+ //
+ Status = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs400);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcRxHs400Tuning: eMMC HS400 Mode Selection Failed!\n"));
+ goto Exit;
+ }
+ //
+ // 3. Set Rx Strobe DLL1 to the Minimal Expected Passing Tap (Smin)
+ // Offset 830h: Rx Strobe Delay DLL 1(HS400 Mode), bits [14:8]
+ // Set Rx Data Strobe DLL2 to middle point 0x13
+ // Offset 830h: Rx Strobe Delay DLL 2(HS400 Mode), bits [6:0]
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning: Set Rx Data DLL1 to the Minimal Expected Passing Tap (Smin = 0x%x)\n", Smin));
+ DllCount = RX_STROBE_DLL1_TAP_MIN_MEPT;
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+
+ //
+ // 4. Read the block that was stored
+ // 5. If CRC fails on first read, increase the DLL Step and repeat block read until passed
+ // Else if CRC passed on first read, decrease the DLL Step and repeat block read until failed
+ // 6. Store the Rx Path min DLL passing step number
+ //
+ FirstRead = NotAvailable;
+ DllMax = RX_STROBE_DLL1_TAP_MAX_RANGE;
+ DllMin = RX_STROBE_DLL1_TAP_MIN_RANGE;
+
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcRxHs400Tuning: Rx Min DLL1 (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (Status == EFI_SUCCESS) {
+ if (FirstRead == NotAvailable) {
+ FirstRead = Passed;
+ } else if (FirstRead == Failed) {
+ Smin = DllCount;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MIN_RANGE) {
+ Smin = RX_STROBE_DLL1_TAP_MIN_RANGE;
+ break;
+ }
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstRead == NotAvailable) {
+ FirstRead = Failed;
+ } else if (FirstRead == Passed) {
+ Smin = DllCount + 1;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MAX_RANGE) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((DEBUG_ERROR, "[Rx DLL Tuning Failed] DllCount == TAP_MAX_RANGE\n"));
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Rx DLL Tuning Failed] Smin - Tuning Blocks Read Error!\n"));
+ goto Exit;
+ }
+
+ if (FirstRead == Failed) {
+ DllCount++;
+ } else {
+ DllCount--;
+ }
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+ }
+
+ DEBUG ((DEBUG_INFO, "[Rx DLL Tuning] Found Minimal Passing Tap = 0x%x\n", Smin));
+
+ //
+ // 7. Set the Rx Strobe DLL1 to the Maximal Expected Passing Tap (Smax)
+ // Offset 830h: Rx Strobe Delay DLL 1(HS400 Mode), bits [14:8]
+ // 8. Read the block that was stored
+ // 9. If CRC fails on first read, decrease the DLL Step and repeat step 8 until pass
+ // Else if CRC passed on first read, increase the DLL Step and repeat step 8 until failed
+ //
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning: Set Rx Data DLL1 to the Maximal Expected Passing Tap (Smax = 0x%x)\n", Smax));
+ DllCount = RX_STROBE_DLL1_TAP_MAX_MEPT;
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+
+ FirstRead = NotAvailable;
+ DllMax = RX_STROBE_DLL1_TAP_MAX_RANGE;
+ DllMin = RX_STROBE_DLL1_TAP_MIN_RANGE;
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcRxHs400Tuning: Rx Max DLL1 (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (Status == EFI_SUCCESS) {
+ if (FirstRead == NotAvailable) {
+ FirstRead = Passed;
+ } else if (FirstRead == Failed) {
+ Smax = DllCount;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MAX_RANGE) {
+ Smax = DllCount;
+ break;
+ }
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstRead == NotAvailable) {
+ FirstRead = Failed;
+ } else if (FirstRead == Passed) {
+ Smax = DllCount - 1;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MIN_RANGE) {
+ Status = EFI_CRC_ERROR;
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Rx DLL Tuning Failed] Smax - Tuning Blocks Read Error!\n"));
+ goto Exit;
+ }
+ if (FirstRead == Failed) {
+ DllCount--;
+ } else {
+ DllCount++;
+ }
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+ }
+ //
+ // 10. Store the Rx Path max DLL Passing Step number
+ //
+
+ //
+ // 11. Compute the Rx DLL Optimal Point (Sopt) = (Smax - Smin)/2 + Smin
+ //
+ Sopt = (Smax - Smin) / 2 + Smin;
+ DEBUG ((DEBUG_INFO, "[Rx DLL Tuning] Optimal Point (Sopt = (Smax[0x%x] - Smin[0x%x]) / 2 + Smin[0x%x]) = 0x%x\n", Smax, Smin, Smin, Sopt));
+ //
+ // 12. Store the Rx DLL optimal value (Sopt)
+ //
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, Sopt);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, Sopt);
+
+ DEBUG ((DEBUG_INFO, "[Rx HS400 Tuning Success] Rx Strobe Delay Control (830h) = 0x%08x\n",
+ MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL)));
+
+ Status = EFI_SUCCESS;
+ EmmcTuningData->Hs400RxStrobe1Dll = Sopt;
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning() End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ To perform HS400 Tx Data Path Training
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in/out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EmmcTxHs400Tuning (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress,
+ IN OUT EMMC_TUNING_DATA *EmmcTuningData
+ )
+{
+ UINT8 *Buffer;
+ UINT8 DllCount;
+ UINT8 DllMax;
+ UINT8 DllMin;
+ UINT8 Smin;
+ UINT8 Smax;
+ UINT8 Sopt;
+ UINT8 N;
+ EFI_STATUS Status;
+ EFI_STATUS ModeStatus;
+ BLOCK_READ_WRITE_STATUS FirstWrite;
+
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning() Start\n"));
+ Status = EFI_SUCCESS;
+ ModeStatus = EFI_SUCCESS;
+
+ Smin = TX_DATA_DLL_TAP_MIN_MEPT;
+ Smax = TX_DATA_DLL_TAP_MAX_MEPT;
+ N = 0;
+
+ Buffer = (VOID *) AllocateZeroPool (BlockIo->Media->BlockSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ //
+ // 1. Read Tuning Block that used at Rx HS400 Tuning
+ //
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ BlockIo->Media->BlockSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTxHs400Tuning: Tuning Block Read at HS400 Mode Failed!\n"));
+ goto Exit;
+ }
+ DEBUG_CODE ( EmmcPrintHs400TuningPattern (BlockIo, Buffer, BlockIo->Media->BlockSize); );
+
+ //
+ // 2. Set Tx Data DLL1 to the Minimal Expected Passing Tap (Smin)
+ // Offset 824h: Tx Data Delay Control 1
+ // Tx Data Delay (HS400 Mode), BIT[14:8]
+ //
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning: Set Tx Data DLL to the Minimal Expected Passing Tap (Smin = 0x%x)\n", Smin));
+
+ DllCount = TX_DATA_DLL_TAP_MIN_MEPT;
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+
+ //
+ // 2. Write Single Block
+ //
+ FirstWrite = NotAvailable;
+ DllMax = TX_DATA_DLL_TAP_MAX_RANGE;
+ DllMin = TX_DATA_DLL_TAP_MIN_RANGE;
+
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcTxHs400Tuning: Tx Min DLL (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->WriteBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ BlockIo->Media->BlockSize,
+ Buffer
+ );
+ if (Status == EFI_SUCCESS) {
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Passed;
+ } else if (FirstWrite == Failed) {
+ Smin = DllCount;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MIN_RANGE) {
+ Smin = TX_DATA_DLL_TAP_MIN_RANGE;
+ break;
+ }
+ //
+ // 3. If CRC fails increment DLL Step and repeat step 2
+ //
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Failed;
+ } else if (FirstWrite == Passed) {
+ Smin = DllCount + 1;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MAX_RANGE) {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] DllCount == TAP_MAX_RANGE\n"));
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] Smin - Tuning Block Write Error!\n"));
+ goto Exit;
+ }
+ if (FirstWrite == Failed) {
+ DllCount++;
+ } else {
+ DllCount--;
+ }
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+ }
+ //
+ // 4. Store the Tx Path min DLL passing step number
+ //
+ DEBUG ((DEBUG_INFO, "[Tx DLL Tuning] Found Minimal Passing Tap = 0x%x\n", Smin));
+
+ //
+ // 5. Set the DLL to max expected passing step (Smax)
+ //
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning: Set Tx Data DLL to the Maximal Expected Passing Tap (Smax = 0x%x)\n", Smax));
+ DllCount = TX_DATA_DLL_TAP_MAX_MEPT;
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+ //
+ // 6. Write Single Block
+ //
+ FirstWrite = NotAvailable;
+ DllMax = TX_DATA_DLL_TAP_MAX_RANGE;
+ DllMin = TX_DATA_DLL_TAP_MIN_RANGE;
+
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcTxHs400Tuning: Tx Max DLL1 (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->WriteBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ BlockIo->Media->BlockSize,
+ Buffer
+ );
+
+ if (Status == EFI_SUCCESS) {
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Passed;
+ } else if (FirstWrite == Failed) {
+ Smax = DllCount;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MAX_RANGE) {
+ Smax = TX_DATA_DLL_TAP_MAX_RANGE;
+ break;
+ }
+ //
+ // 7. If CRC fails decrement DLL Step and repeat step 6
+ //
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Failed;
+ } else if (FirstWrite == Passed) {
+ Smax = DllCount - 1;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MIN_RANGE) {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] DllCount == TAP_MIN_RANGE\n"));
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] Smax - Tuning Block Write Error!\n"));
+ goto Exit;
+ }
+ if (FirstWrite == Failed) {
+ DllCount--;
+ } else {
+ DllCount++;
+ }
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+ }
+ //
+ // 8. Store the DLL passing step number (Smax)
+ //
+ DEBUG ((DEBUG_INFO, "[Tx DLL Tuning] Found Maximal Passing Tap = 0x%x\n", Smax));
+
+ N = Smax - Smin;
+ if (N <= 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // 9. Compute the Tx DLL Optimal point (Sopt) = (Smax - Smin) / 2 + Smin
+ //
+ Sopt = (Smax - Smin) / 2 + Smin;
+ DEBUG ((DEBUG_INFO, "[Tx DLL Tuning] Optimal Point (Sopt = (Smax[0x%x] - Smin[0x%x]) / 2 + Smin[0x%x]) = 0x%x\n", Smax, Smin, Smin, Sopt));
+
+ //
+ // 10. Store the Tx Strobe DLL Optimal point value
+ //
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, Sopt);
+
+ DEBUG ((DEBUG_INFO, "[Tx HS400 Tuning Success] Tx Data Delay Control 1 (824h) = 0x%08x\n",
+ MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1)));
+
+ Status = EFI_SUCCESS;
+ EmmcTuningData->Hs400TxDataDll = Sopt;
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning() End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ To perform write protection checking on the address to write
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EmmcWriteProtectCheck (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT32 DataSize;
+ UINT32 CardStatus;
+ UINT32 Address;
+ UINT32 Timeout;
+ UINT16 CommandIndex;
+ UINT8 *Buffer;
+
+ Status = EFI_SUCCESS;
+ DataSize = 8;
+ CommandIndex = SEND_WRITE_PROT_TYPE;
+ Timeout = TIMEOUT_DATA;
+
+ Buffer = (VOID *) AllocateZeroPool (DataSize);
+ Address = (UINT32) DivU64x32 (MultU64x32 (EmmcInfo->Lba, BlockIo->Media->BlockSize), 512);
+
+ DEBUG ((DEBUG_INFO, "EmmcWriteProtectCheck() Start\n"));
+
+ if (BlockIo->Media->ReadOnly == TRUE) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ CommandIndex,
+ Address,
+ InData,
+ Buffer,
+ DataSize,
+ ResponseR1,
+ Timeout,
+ &CardStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Buffer[7] & (BIT0 | BIT1)) !=0) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcWriteProtectCheck End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ Configure eMMC in HS400 Mode
+
+ @param[in] This A pointer to PCH_EMMC_TUNING_PROTOCOL structure
+ @param[in] Revision Revision parameter used to verify the layout of EMMC_INFO and TUNINGDATA.
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND The item was not found
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EFIAPI
+ConfigureEmmcHs400Mode (
+ IN PCH_EMMC_TUNING_PROTOCOL *This,
+ IN UINT8 Revision,
+ IN EMMC_INFO *EmmcInfo,
+ OUT EMMC_TUNING_DATA *EmmcTuningData
+ )
+{
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status;
+ EFI_STATUS ModeStatus;
+ UINTN EmmcBaseAddress;
+ UINTN EmmcPciBaseAddress;
+ ModeStatus = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode() Start\n"));
+ EmmcTuningData->Hs400DataValid = FALSE;
+ //
+ // Check PCH_EMMC_TUNING_PROTOCOL_REVISION
+ //
+ if (Revision != PCH_EMMC_TUNING_PROTOCOL_REVISION) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: PCH eMMC Tuning Protocol Revision Not Match! Tuning Aborted\n"));
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get eMMC Host Controller Mmio base register
+ //
+ EmmcPciBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SCS_EMMC,
+ PCI_FUNCTION_NUMBER_PCH_SCS_EMMC
+ );
+
+ if (MmioRead16 (EmmcPciBaseAddress + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: eMMC Host Controller Unavailable!\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Assume BAR is ready since it's executed after blockio ready, handling 64bit BAR in DXE is not required
+ //
+ EmmcBaseAddress = MmioRead32 (EmmcPciBaseAddress + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFF000;
+ //
+ // Enable Memory Decode
+ //
+ if ((MmioRead8 (EmmcPciBaseAddress + PCI_COMMAND_OFFSET) & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
+ MmioOr8 (EmmcPciBaseAddress + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ DEBUG ((DEBUG_INFO, "Initial HS400 DLL values (set in PEI):\n"));
+ DEBUG ((DEBUG_INFO, "Tx Data Delay Control 1 (824h) = 0x%08x\n", MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1)));
+ DEBUG ((DEBUG_INFO, "Rx Strobe Delay Control (830h) = 0x%08x\n", MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL)));
+
+ if (mPchConfigHob->Scs.ScsEmmcHs400TuningRequired == FALSE) {
+ if (mPchConfigHob->Scs.ScsEmmcHs400DllDataValid == TRUE) {
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode: SCS eMMC 5.0 HS400 Tuning Not Required, set device to HS400 mode\n"));
+ Status = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs400);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: eMMC HS400 Mode Selection Failed!\n"));
+ }
+ return Status;
+ } else {
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode: SCS eMMC 5.0 HS400 Mode Selection Not Required.\n"));
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Handle Platform Emmc Info Protocol for Efi Block Io Protocol
+ //
+ Status = gBS->HandleProtocol (
+ EmmcInfo->PartitionHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID**) &BlockIo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: BlockIo: Platform Emmc Info Protocol Handle Not Found!\n"));
+ EmmcHostHs400Disabled (EmmcBaseAddress);
+ return Status;
+ }
+
+ //
+ // Write Protection checking on the region
+ //
+ Status = EmmcWriteProtectCheck (EmmcInfo, BlockIo, EmmcBaseAddress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: Region is write protected! HS400 Tuning Abort!\n"));
+ EmmcHostHs400Disabled (EmmcBaseAddress);
+ return Status;
+ }
+
+ Status = EmmcWriteHs400TuningPattern (EmmcInfo, BlockIo, EmmcBaseAddress, (UINT8*)EmmcWorstCasePattern);
+
+ //
+ // Rx HS400 Auto Tuning
+ //
+ Status = EmmcRxHs400Tuning (EmmcInfo, BlockIo, EmmcBaseAddress, EmmcTuningData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: Rx HS400 Auto Tuning Failed!\n"));
+ ModeStatus = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs200);
+ if (EFI_ERROR (ModeStatus)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTxHs400Tuning: eMMC HS200 Mode Selection Failed!\n"));
+ }
+ EmmcTuningData->Hs400DataValid = FALSE;
+ return Status;
+ }
+
+ //
+ // Tx HS400 Auto Tuning
+ //
+ Status = EmmcTxHs400Tuning (EmmcInfo, BlockIo, EmmcBaseAddress, EmmcTuningData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: Tx HS400 Auto Tuning Failed!\n"));
+ ModeStatus = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs200);
+ if (EFI_ERROR (ModeStatus)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTxHs400Tuning: eMMC HS200 Mode Selection Failed!\n"));
+ }
+ EmmcTuningData->Hs400DataValid = FALSE;
+ return Status;
+ }
+
+ //
+ // Set current HS400 Driver Strength in tuning data structre
+ // Set HS400 Data Valid Tuning Bit to TRUE
+ //
+ EmmcTuningData->Hs400DriverStrength = (UINT8) mPchConfigHob->Scs.ScsEmmcHs400DriverStrength;
+ EmmcTuningData->Hs400DataValid = TRUE;
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode() End\n"));
+ return Status;
+}
+
+/**
+ Install PCH EMMC TUNING PROTOCOL
+
+**/
+VOID
+InstallPchEmmcTuningProtocol (
+ VOID
+ )
+{
+
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ Handle = NULL;
+
+ ///
+ /// For normal boot flow
+ /// 1. If ScsEmmcEnabled and ScsEmmcHs400Enabled policy set,
+ /// a) Set ScsEmmcHs400TuningRequired policy to state tuning required in PEI,
+ /// - if RTC_PWR_STS bit is set which indicates a new coin-cell battery insertion, a battery failure or CMOS clear.(Boot with default settings)
+ /// - if non-volatile variable 'Hs400TuningData' does not exist
+ /// b) RC installed Pch Emmc Tuning Protocol regardless of ScsEmmcHs400TuningRequired policy setting.in DXE
+ /// c) If boot with default settings after CMOS cleared, platform delete variable 'Hs400TuningData' in DXE
+ /// 2. Once RC successfully installed Pch Emmc Tuning Protocol, it will be used to perform EmmcTune for Hs400.
+ /// 3. Then, platform must set the variable with returned EmmcTuningData no matter tuning pass of fail
+ /// 4. Platform shall set variable 'Hs400TuningData' for one time only or after CMOS clear
+ ///
+ /// For fast boot flow
+ /// 1. If ScsEmmcEnabled and ScsEmmcHs400Enabled policy set,
+ /// a) Set ScsEmmcHs400TuningRequired policy to state tuning not required, if non-volatile variable 'Hs400TuningData' exist
+ /// b) RC installed Pch Emmc Tuning Protocol regardless of ScsEmmcHs400TuningRequired policy setting in DXE
+ /// 2. Once RC successfully installed Pch Emmc Tuning Protocol, it will be used to perform EmmcTune
+ /// 3. Since ScsEmmcHs400TuningRequired state tuning not required, RC will not perform Emmc Hs400 Tuning but just set the device to operate in HS400 mode if data is valid
+ /// 4. Platform shall not set variable 'Hs400TuningData'
+ ///
+ //
+ // Install PchEmmcTuningProtocol Protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gPchEmmcTuningProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &PchEmmcTuningProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
new file mode 100644
index 0000000000..013c729ddf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
@@ -0,0 +1,49 @@
+/** @file
+ Initializes Serial IO Controllers.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PchInit.h>
+#include <Library/PchSerialIoLib.h>
+
+
+/**
+ Puts all SerialIo controllers (except UARTs in debug mode) in D3
+ Clears MemoryEnable for all PCI-mode controllers
+**/
+EFI_STATUS
+ConfigureSerialIoAtBoot (
+ VOID
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Index;
+ UINTN PciCfgBase;
+
+ for (Index = 0; Index < PchSerialIoIndexMax; Index++) {
+ if ((mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoDisabled) ||
+ (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoSkipInit) ) {
+ continue;
+ }
+ if ((Index >= PchSerialIoIndexUart0) &&
+ (mPchConfigHob->SerialIo.EnableDebugUartAfterPost) &&
+ (mPchConfigHob->SerialIo.DebugUartNumber == (UINT32) (Index - PchSerialIoIndexUart0))) {
+ continue;
+ }
+ PciCfgBase = FindSerialIoBar (Index,1);
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_PME_CTRL_STS, B_PCH_SERIAL_IO_PME_CTRL_STS_PWR_ST);
+ MmioRead32 (PciCfgBase + R_PCH_SERIAL_IO_PME_CTRL_STS);
+ if (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoPci) {
+ MmioAnd32 (PciCfgBase + PCI_COMMAND_OFFSET, (UINT32)~(EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER) );
+ }
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
new file mode 100644
index 0000000000..3b951092b5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
@@ -0,0 +1,112 @@
+/** @file
+ Initializes Serial IO Controllers.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PchInit.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/DevicePathLib.h>
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH RootPort;
+ ACPI_EXTENDED_HID_DEVICE_PATH AcpiDev;
+ CHAR8 HidString[8];
+ CHAR8 UidString;
+ CHAR8 CidString;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SERIALIO_DEVICE_PATH;
+
+#define gPciRootBridge {{ACPI_DEVICE_PATH, ACPI_DP, {(UINT8)(sizeof(ACPI_HID_DEVICE_PATH)), 0}}, EISA_PNP_ID (0x0A03), 0}
+#define gAcpiDev {{ACPI_DEVICE_PATH,ACPI_EXTENDED_DP,{(UINT8)(sizeof(ACPI_EXTENDED_HID_DEVICE_PATH)+SERIALIO_TOTAL_ID_LENGTH),0}},0,0,0}
+#define gEndEntire {END_DEVICE_PATH_TYPE,END_ENTIRE_DEVICE_PATH_SUBTYPE,{END_DEVICE_PATH_LENGTH,0}}
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIALIO_DEVICE_PATH gSerialIoPath = {
+ gPciRootBridge,
+ gAcpiDev,
+ "\0\0\0\0\0\0\0",
+ '\0',
+ '\0',
+ gEndEntire
+};
+
+/**
+Mark memory used by SerialIo devices in ACPI mode as allocated
+
+@retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+AllocateSerialIoMemory (
+ VOID
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER i;
+ UINT8 BarNumber;
+ UINTN Bar;
+ EFI_STATUS Status;
+
+ for (i=0; i<PchSerialIoIndexMax; i++) {
+ if (mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoAcpiHidden ||
+ mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoLegacyUart ||
+ mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoAcpi) {
+ for (BarNumber = 0; BarNumber<=1; BarNumber++) {
+ Bar = FindSerialIoBar (i,BarNumber);
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeReserved,
+ Bar,
+ V_PCH_SERIAL_IO_BAR_SIZE,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeReserved,
+ N_PCH_SERIAL_IO_BAR_ALIGNMENT,
+ V_PCH_SERIAL_IO_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;
+ EFI_STATUS Status;
+ UINT32 Controller;
+
+ for (Controller = 0; Controller < PchSerialIoIndexMax; Controller++) {
+ if (mPchConfigHob->SerialIo.DevMode[Controller] == PchSerialIoAcpi) {
+ NewHandle = NULL;
+ CopyMem (gSerialIoPath.HidString, GetSerialIoAcpiHID (Controller), SERIALIO_HID_LENGTH);
+ NewPath = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL*)&gSerialIoPath);
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &NewHandle,
+ &gEfiDevicePathProtocolGuid,
+ NewPath,
+ NULL );
+ }
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
new file mode 100644
index 0000000000..cfaf0d57bd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
@@ -0,0 +1,130 @@
+/** @file
+ PCH BIOS Write Protect Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInitSmm.h"
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_TCO_SMI_DISPATCH_PROTOCOL *mPchTcoSmiDispatchProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSpiRegBase;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_ESPI_SMI_DISPATCH_PROTOCOL *mEspiSmmDispatchProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLpcRegBase;
+
+/**
+ This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchSpiBiosWpCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Disable BIOSWE bit to protect BIOS
+ //
+ MmioAnd8 ((UINTN) (mSpiRegBase + R_PCH_SPI_BC), (UINT8) ~B_PCH_SPI_BC_WPD);
+}
+
+/**
+ This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchLpcBiosWpCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Disable BIOSWE bit to protect BIOS
+ //
+ MmioAnd8 ((UINTN) (mLpcRegBase + R_PCH_LPC_BC), (UINT8) ~B_PCH_LPC_BC_WPD);
+}
+
+/**
+ Entry point for Pch Bios Write Protect driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchBiosWriteProtect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ DEBUG ((DEBUG_INFO, "InstallPchBiosWriteProtect()\n"));
+
+ if (mPchConfigHob->LockDown.BiosLock != TRUE) {
+ return EFI_SUCCESS;
+ }
+
+ mSpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+
+ mLpcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ DEBUG ((DEBUG_INFO, "Installing BIOS Write Protect SMI handler\n"));
+
+ //
+ // Get the PCH TCO SMM dispatch protocol
+ //
+ mPchTcoSmiDispatchProtocol = NULL;
+ Status = gSmst->SmmLocateProtocol (&gPchTcoSmiDispatchProtocolGuid, NULL, (VOID **) &mPchTcoSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Always register an SPI BiosWp callback function to handle TCO BIOSWR SMI
+ // NOTE: No matter the BIOS resides behind SPI or not, it needs to handle the SPI BIOS WP SMI
+ // to avoid SMI deadloop on SPI WPD write.
+ //
+ Handle = NULL;
+ Status = mPchTcoSmiDispatchProtocol->SpiBiosWpRegister (
+ mPchTcoSmiDispatchProtocol,
+ PchSpiBiosWpCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register an LPC BiosWp callback function to handle TCO BIOSWR SMI
+ //
+ Handle = NULL;
+ Status = mPchTcoSmiDispatchProtocol->LpcBiosWpRegister (
+ mPchTcoSmiDispatchProtocol,
+ PchLpcBiosWpCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c
new file mode 100644
index 0000000000..4c3dd6cf11
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c
@@ -0,0 +1,48 @@
+/** @file
+ PCH GPIO Sx Isolation Driver Entry
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInitSmm.h"
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+
+/**
+ This function performs GPIO Sx Isolation for DevSlp pins.
+**/
+VOID
+PchGpioSxIsolationCallback (
+ VOID
+ )
+{
+ UINT32 SataPortsMax;
+ UINT32 SataPort;
+ GPIO_PAD DevSlpGpioPad;
+
+ SataPortsMax = GetPchMaxSataPortNum ();
+
+ //
+ // If DevSlp pad is used in its native mode then
+ // set PadRstCfg to 10'b (GPIO Reset)
+ //
+ for (SataPort = 0; SataPort < SataPortsMax; SataPort++) {
+ //
+ // Check if DevSlp pad is in native mode
+ //
+ if (GpioIsSataDevSlpPinEnabled (SataPort, &DevSlpGpioPad)) {
+ //
+ // Program PADCFG_DW0.PadRstCfg
+ //
+ GpioSetPadResetConfig (DevSlpGpioPad, GpioResetNormal);
+ }
+ }
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
new file mode 100644
index 0000000000..c6e1809946
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
@@ -0,0 +1,308 @@
+/** @file
+ PCH Init Smm module for PCH specific SMI handlers.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInitSmm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA *mPchNvsArea;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mAcpiBaseAddr;
+
+//
+// NOTE: The module variables of policy here are only valid in post time, but not runtime time.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *mPchConfigHob;
+GLOBAL_REMOVE_IF_UNREFERENCED SI_CONFIG_HOB *mSiConfigHob;
+
+//
+// The reserved MMIO range to be used in Sx handler
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mResvMmioSize;
+//
+// The reserved MMIO range to be used by xHCI ASL code
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS mXhciMmioBaseAddr;
+
+/**
+ SMBUS Sx entry SMI handler.
+**/
+VOID
+SmbusSxCallback (
+ VOID
+ )
+{
+ UINTN SmbusRegBase;
+ UINT16 SmbusIoBase;
+
+ SmbusRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+
+ if (MmioRead32 (SmbusRegBase) == 0xFFFFFFFF) {
+ return;
+ }
+
+ SmbusIoBase = MmioRead16 (SmbusRegBase + R_PCH_SMBUS_BASE) & B_PCH_SMBUS_BASE_BAR;
+ if (SmbusIoBase == 0) {
+ return;
+ }
+
+ MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_IO_SPACE);
+ //
+ // Clear SMBUS status and SMB_WAK_STS of GPE0
+ //
+ IoWrite8 (SmbusIoBase + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_SMBALERT_STS);
+ IoWrite32 (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96, B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK);
+}
+
+/**
+ PCH Sx entry SMI handler.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in,out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in,out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PchSxHandler (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ PchGpioSxIsolationCallback ();
+ PchLanSxCallback ();
+
+ if (((EFI_SMM_SX_REGISTER_CONTEXT*)Context)->Type == SxS3) {
+ PchXhciS3Callback ();
+ }
+
+ SmbusSxCallback ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize PCH Sx entry SMI handler.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+**/
+VOID
+InitializeSxHandler (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ EFI_HANDLE SxDispatchHandle;
+ EFI_SLEEP_TYPE SxType;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "InitializeSxHandler() Start\n"));
+
+ //
+ // Register the callback for S3/S4/S5 entry
+ //
+ SxDispatchContext.Phase = SxEntry;
+ for (SxType = SxS3; SxType <= SxS5; SxType++) {
+ SxDispatchContext.Type = SxType;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ PchSxHandler,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ DEBUG ((DEBUG_INFO, "InitializeSxHandler() End\n"));
+}
+
+/**
+ Allocates reserved MMIO for Sx SMI handler use.
+
+ This function is only called from entry point therefore DXE/boot Services can be used here.
+ Updates ACPI NVS location to reserve allocated MMIO range as system resource.
+**/
+VOID
+AllocateReservedMmio (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+ EFI_STATUS Status;
+
+ mResvMmioSize = 1 << N_PCH_LAN_MBARA_ALIGN;
+
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ mResvMmioBaseAddr = 0xFFFFFFFF;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ N_PCH_LAN_MBARA_ALIGN,
+ mResvMmioSize,
+ &mResvMmioBaseAddr,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "mResvMmioBaseAddr %x\n", mResvMmioBaseAddr));
+
+ //
+ // Locate the PCH shared data area and update reserved memory base address
+ //
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ PchNvsAreaProtocol->Area->SxMemSize = (UINT32) mResvMmioSize;
+ PchNvsAreaProtocol->Area->SxMemBase = (UINT32) mResvMmioBaseAddr;
+
+ //
+ // Install and initialize all the needed protocols
+ //
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ mXhciMmioBaseAddr = 0xFFFFFFFF;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ N_PCH_XHCI_MEM_ALIGN,
+ V_PCH_XHCI_MEM_LENGTH,
+ &mXhciMmioBaseAddr,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "mXhciMmioBaseAddr %x\n", mXhciMmioBaseAddr));
+
+ //
+ // Update XWMB, XHCI memory base address
+ //
+ PchNvsAreaProtocol->Area->XhciRsvdMemBase = (UINT32) mXhciMmioBaseAddr;
+}
+
+/**
+ Initializes the PCH SMM handler for for PCIE hot plug support
+ <b>PchInit SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchInitSmm module is a SMM driver that initializes the Intel Platform Controller Hub
+ SMM requirements and services. It consumes the PCH_POLICY_HOB and SI_POLICY_HOB for expected
+ configurations per policy.
+
+ - <b>Details</b>\n
+ This module provides SMI handlers to services PCIE HotPlug SMI, LinkActive SMI, and LinkEq SMI.
+ And also provides port 0x61 emulation support, registers BIOS WP handler to process BIOSWP status,
+ and registers SPI Async SMI handler to handler SPI Async SMI.
+ This module also registers Sx SMI callback function to detail with GPIO Sx Isolation and LAN requirement.
+
+ - @pre
+ - PCH PCR base address configured
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+ - EFI_SMM_BASE2_PROTOCOL
+ - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+ - EFI_SMM_SX_DISPATCH2_PROTOCOL
+ - EFI_SMM_CPU_PROTOCOL
+ - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL @endlink
+ - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL @endlink
+
+ - <b>References</b>\n
+ - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
+ - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink.
+
+ - <b>Integration Checklists</b>\n
+ - Verify prerequisites are met. Porting Recommendations.
+ - No modification of this module should be necessary
+ - Any modification of this module should follow the PCH BIOS Specification and EDS
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - PCH SMM handler was installed
+**/
+EFI_STATUS
+EFIAPI
+PchInitSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ DEBUG ((DEBUG_INFO, "PchInitSmmEntryPoint()\n"));
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmIoTrapDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &mPchIoTrap
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ (VOID**) &mSxDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPchNvsArea = PchNvsAreaProtocol->Area;
+
+ //
+ // Get PCH Data HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gPchConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ HobPtr.Guid = GetFirstGuidHob (&gSiConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mSiConfigHob = (SI_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ PchAcpiBaseGet (&mAcpiBaseAddr);
+
+ AllocateReservedMmio (ImageHandle);
+
+ InitializeSxHandler (ImageHandle);
+
+ Status = InitializePchPcieSmm (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallIoTrapPort61h (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallPchBiosWriteProtect (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallPchSpiAsyncSmiHandler ();
+ ASSERT_EFI_ERROR (Status);
+
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
new file mode 100644
index 0000000000..58ef567cc0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
@@ -0,0 +1,344 @@
+/** @file
+ Header file for PCH Init SMM Handler
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_INIT_SMM_H_
+#define _PCH_INIT_SMM_H_
+
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/HobLib.h>
+#include <Protocol/SmmCpu.h>
+
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/PchEspiLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Protocol/PchEspiSmiDispatch.h>
+#include <Protocol/PchSmmIoTrapControl.h>
+#include <Protocol/PchNvs.h>
+#include <Protocol/PcieIoTrap.h>
+#include <SiConfigHob.h>
+#include <PchConfigHob.h>
+
+extern EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+extern EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+extern PCH_NVS_AREA *mPchNvsArea;
+extern UINT16 mAcpiBaseAddr;
+
+extern EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+extern EFI_PHYSICAL_ADDRESS mXhciMmioBaseAddr;
+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 *mSiConfigHob;
+
+#define EFI_PCI_CAPABILITY_ID_PCIPM 0x01
+
+#define DeviceD0 0x00
+#define DeviceD3 0x03
+
+typedef enum {
+ PciCfg,
+ PciMmr
+} PCH_PCI_ACCESS_TYPE;
+
+typedef enum {
+ Acpi,
+ Rcrb,
+ Tco
+} PCH_ACCESS_TYPE;
+
+typedef struct {
+ PCH_ACCESS_TYPE AccessType;
+ UINT32 Address;
+ UINT32 Data;
+ UINT32 Mask;
+ UINT8 Width;
+} PCH_SAVE_RESTORE_REG;
+
+typedef struct {
+ PCH_SAVE_RESTORE_REG* PchSaveRestoreReg;
+ UINT8 size;
+ PCH_SERIES PchSeries;
+} PCH_SAVE_RESTORE_REG_WRAP;
+
+struct _PCH_SAVE_RESTORE_PCI;
+
+typedef struct _PCH_SAVE_RESTORE_PCI{
+ PCH_PCI_ACCESS_TYPE AccessType;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 BarOffset;
+ UINT16 Offset;
+ UINT32 Data;
+ UINT32 Mask;
+ UINT8 Width;
+ VOID (*RestoreFunction)(struct _PCH_SAVE_RESTORE_PCI *PchSaveRestorePci);
+} PCH_SAVE_RESTORE_PCI;
+
+typedef struct {
+ PCH_SAVE_RESTORE_PCI* PchSaveRestorePci;
+ UINT8 size;
+ PCH_SERIES PchSeries;
+} PCH_SAVE_RESTORE_PCI_WRAP;
+
+typedef struct {
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 PowerState;
+} DEVICE_POWER_STATE;
+
+VOID
+RestorePxDevSlp(
+ IN PCH_SAVE_RESTORE_PCI *PchSaveRestorePci
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+
+ @retval EFI_SUCCESS Root port complete successfully
+ @retval EFI_UNSUPPORTED PMC has invalid vendor ID
+**/
+EFI_STATUS
+PchPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ );
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieSmiRpHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ PCIE Link Equalization Request SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+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
+ );
+
+/**
+ Locate required protocol and register the 61h IO trap
+
+ @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
+InstallIoTrapPort61h (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Initialize PCH Sx entry SMI handler.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+**/
+VOID
+InitializeSxHandler (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ PCH Sx entry SMI handler.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in,out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in,out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS
+**/
+
+EFI_STATUS
+EFIAPI
+PchSxHandler (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+/**
+ xHCI S3 entry handler
+**/
+VOID
+PchXhciS3Callback (
+ VOID
+ );
+
+/**
+ GbE Sx entry handler
+**/
+VOID
+PchLanSxCallback (
+ VOID
+ );
+
+/**
+ This function performs GPIO Sx Isolation for DevSlp pins.
+**/
+VOID
+PchGpioSxIsolationCallback (
+ VOID
+ );
+
+/**
+ 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/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
new file mode 100644
index 0000000000..458eac090e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
@@ -0,0 +1,107 @@
+## @file
+# Component description file for PchInitSmm driver
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchInitSmm
+FILE_GUID = D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = PchInitSmmEntryPoint
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+DxeServicesTableLib
+IoLib
+DebugLib
+BaseLib
+BaseMemoryLib
+S3BootScriptLib
+PchPciExpressHelpersLib
+SmmServicesTableLib
+MmPciLib
+HobLib
+GpioLib
+GpioPrivateLib
+ReportStatusCodeLib
+DevicePathLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchInfoLib
+TimerLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchInitSmm.c
+PchPcieSmm.c
+PchPort61hSmm.c
+PchGpioSxIsolationSmm.c
+PchLanSxSmm.c
+PchInitSmm.h
+PchBiosWriteProtect.c
+PchSpiAsync.c
+PchXhciSxSmm.c
+
+
+[Protocols]
+gEfiSmmIoTrapDispatch2ProtocolGuid ## CONSUMES
+gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES
+gPchSmmIoTrapControlGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gPchNvsAreaProtocolGuid ## CONSUMES
+gPchPcieSmiDispatchProtocolGuid ## CONSUMES
+gPchTcoSmiDispatchProtocolGuid ## CONSUMES
+gPchSmiDispatchProtocolGuid ## CONSUMES
+gPchEspiSmiDispatchProtocolGuid ## CONSUMES
+gPchPcieIoTrapProtocolGuid ## PRODUCES
+
+
+[Guids]
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+gPchDeviceTableHobGuid
+
+
+[Depex]
+gEfiSmmIoTrapDispatch2ProtocolGuid AND
+gEfiSmmSxDispatch2ProtocolGuid AND
+gPchSmmIoTrapControlGuid AND
+gPchPcieSmiDispatchProtocolGuid AND
+gPchTcoSmiDispatchProtocolGuid AND
+gEfiSmmCpuProtocolGuid AND
+gPchNvsAreaProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmBase2ProtocolGuid # This is for SmmServicesTableLib
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
new file mode 100644
index 0000000000..d05cb61bbc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
@@ -0,0 +1,415 @@
+/** @file
+ PCH LAN Sx handler implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/TimerLib.h>
+#include "PchInitSmm.h"
+
+//
+// Maximum loop time for GbE status check
+//
+#define GBE_MAX_LOOP_TIME 4000
+
+/**
+ Checks if Lan is Enabled or Disabled
+
+ @retval BOOLEAN TRUE if device is enabled, FALSE otherwise.
+**/
+BOOLEAN
+IsGbeEnabled (
+ VOID
+ )
+{
+ UINTN GbePciBase;
+
+ GbePciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LAN,
+ PCI_FUNCTION_NUMBER_PCH_LAN
+ );
+
+ if (MmioRead32 (GbePciBase) != 0xFFFFFFFF) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+/**
+ Test for MDIO operation complete.
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeMdiWaitReady (
+ UINT32 GbeBar
+ )
+{
+ UINT32 Count;
+
+ for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+ if (MmioRead32 (GbeBar + R_PCH_LAN_CSR_MDIC) & B_PCH_LAN_CSR_MDIC_RB) {
+ return EFI_SUCCESS;
+ }
+ MicroSecondDelay (50);
+ }
+ return EFI_TIMEOUT;
+}
+
+/**
+ Acquire MDIO software semaphore.
+
+ 1. Ensure that MBARA offset F00h [5] = 1b
+ 2. Poll MBARA offset F00h [5] up to 200ms
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeAcquireMdio (
+ IN UINT32 GbeBar
+ )
+{
+ UINT32 ExtCnfCtrl;
+ UINT32 Count;
+
+ MmioOr32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL, B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG);
+ for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+ ExtCnfCtrl = MmioRead32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL);
+ if (ExtCnfCtrl & B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG) {
+ return EFI_SUCCESS;
+ }
+ MicroSecondDelay (50);
+ }
+ ASSERT (FALSE);
+ return EFI_TIMEOUT;
+}
+
+
+/**
+ Release MDIO software semaphore by clearing MBARA offset F00h [5]
+
+ @param [in] GbeBar GbE MMIO space
+**/
+VOID
+GbeReleaseMdio (
+ IN UINT32 GbeBar
+ )
+{
+ ASSERT (MmioRead32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL) & B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG);
+ MmioAnd32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL, (UINT32) ~B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG);
+ ASSERT ((MmioRead32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL) & B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG) == 0);
+}
+
+/**
+ Perform MDI write.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] Data Value to write in lower 16bits, upper 16bit may contain opcode.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+GbeMdiWrite (
+ IN UINT32 GbeBar,
+ IN UINT32 Data
+ )
+{
+ MmioWrite32 (GbeBar + R_PCH_LAN_CSR_MDIC, Data | 0x04000000);
+ return GbeMdiWaitReady (GbeBar);
+}
+
+/**
+ Perform MDI read.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] Command MDI command
+ @param [out] Data Value read
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+GbeMdiRead (
+ IN UINT32 GbeBar,
+ IN UINT32 Command,
+ OUT UINT16 *Data
+ )
+{
+ EFI_STATUS Status;
+ MmioWrite32 (GbeBar + R_PCH_LAN_CSR_MDIC, Command | 0x08000000);
+ Status = GbeMdiWaitReady (GbeBar);
+ *Data = (UINT16) MmioRead32 (GbeBar + R_PCH_LAN_CSR_MDIC);
+ return Status;
+}
+
+/**
+ Configure WOL during Sx entry.
+
+ @param [in] GbeBar GbE MMIO space
+**/
+VOID
+GbeWolWorkaround (
+ IN UINT32 GbeBar
+ )
+{
+ UINT32 RAL0;
+ UINT32 RAH0;
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ //
+ // System BIOS performs read from MBARA offset 5400h [31:0] and MBARA offset 5404h [31:0]
+ //
+ RAL0 = MmioRead32 (GbeBar + R_PCH_LAN_CSR_RAL);
+ RAH0 = MmioRead32 (GbeBar + R_PCH_LAN_CSR_RAH);
+
+ //
+ // Set MBARA offset 20h = 0x043f6400
+ //
+ Status = GbeMdiWrite (GbeBar, 0x043f6400);
+
+ //
+ // If timeout is reached, force MAC to SMB and try again
+ // Assert if failed on second attempt
+ //
+ if (Status == EFI_TIMEOUT) {
+ //
+ // Change Extended Device Control Register BIT 11 to 1 which
+ // forces the interface between the MAC and the Phy to be on SMBus.
+ // Cleared on the assertion of PCI reset.
+ //
+ MmioOr32 (GbeBar + R_PCH_LAN_CSR_CTRL_EXT, B_PCH_LAN_CSR_CTRL_EXT_FORCE_SMB);
+ Status = GbeMdiWrite (GbeBar, 0x043f6400);
+ }
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Wait 4 mSec
+ //
+ MicroSecondDelay (4000);
+
+ //
+ // Set MBARA offset 20h = 0x4310010
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310010);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 or with
+ // the least significant word of MBARA offset 5400
+ //
+ Status = GbeMdiWrite (GbeBar, (0x04320000 | (RAL0 & 0xFFFF)));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310011
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310011);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 or with
+ // the most significant word of MBARA offset 5400
+ //
+ Status = GbeMdiWrite (GbeBar, (0x04320000 | (RAL0 >> 16)));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310012
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310012);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 or with
+ // the least significant word of MBARA offset 5404
+ //
+ Status = GbeMdiWrite (GbeBar, (0x04320000 | (RAH0 & B_PCH_LAN_CSR_RAH_RAH)));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310013
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310013);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4328000
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04328000);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310001
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310001);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x8320000
+ //
+ Status = GbeMdiRead (GbeBar, 0x08320000, &Data16);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 OR TEMP[15:0] OR 1
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04320000 | Data16 | BIT0);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x43f6460
+ //
+ Status = GbeMdiWrite (GbeBar, 0x043f6460);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Wait 4 mSec
+ //
+ MicroSecondDelay (4000);
+
+ //
+ // Set MBARA offset 20h = 0x4310042
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310042);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x43F6020
+ //
+ Status = GbeMdiWrite (GbeBar, 0x043F6020);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Wait 4 mSec
+ //
+ MicroSecondDelay (4000);
+
+ //
+ // Set MBARA offset 20h = 0x8310000
+ // TEMP[15:0] = MBARA + 20[15:0]
+ //
+ Status = GbeMdiRead (GbeBar, 0x08310000, &Data16);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA + 20h = 4310000h or with the TEMP[15:0] OR 10h
+ //
+ GbeMdiWrite (GbeBar, 0x04310000 | Data16 | BIT4);
+}
+
+/**
+ Additional Internal GbE Controller special cases WOL Support.
+
+ System BIOS is required perform additional steps upon S0 to S3,4,5 transition
+ when ME is off and GbE device in D0. This is needed to enable LAN wake
+ in particular when platform is shut-down from EFI.
+**/
+VOID
+GbeSxWorkaround (
+ VOID
+ )
+{
+ UINTN LanRegBase;
+ UINT32 GbeBar;
+ EFI_STATUS Status;
+
+ LanRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LAN,
+ PCI_FUNCTION_NUMBER_PCH_LAN
+ );
+
+ if (MmioRead16 (LanRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+
+ //
+ // Check if GbE device is in D0
+ //
+ if ((MmioRead16 (LanRegBase + R_PCH_LAN_PMCS) & B_PCH_LAN_PMCS_PS) != V_PCH_LAN_PMCS_PS0) {
+ return;
+ }
+
+ ASSERT (mResvMmioSize >= (1 << N_PCH_LAN_MBARA_ALIGN));
+ GbeBar = (UINT32) mResvMmioBaseAddr;
+ if (GbeBar == 0) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Enable MMIO decode using reserved range.
+ //
+ MmioAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (LanRegBase + R_PCH_LAN_MBARA, GbeBar);
+ MmioOr16 (LanRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // If MBARA offset 5800h [0] = 1b then proceed with the w/a
+ //
+ if (MmioRead32 (GbeBar + R_PCH_LAN_CSR_WUC) & B_PCH_LAN_CSR_WUC_APME) {
+ Status = GbeAcquireMdio (GbeBar);
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ GbeWolWorkaround (GbeBar);
+ GbeReleaseMdio (GbeBar);
+ }
+ }
+
+ //
+ // Disable MMIO decode.
+ //
+ MmioAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (LanRegBase + R_PCH_LAN_MBARA, 0);
+}
+
+/**
+ Enable platform wake from LAN when in DeepSx if platform supports it.
+ Called upon Sx entry.
+**/
+VOID
+GbeConfigureDeepSxWake (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ if ((MmioRead32 (PchPwrmBase + R_PCH_PWRM_DSX_CFG) & (UINT32) B_PCH_PWRM_DSX_CFG_LAN_WAKE_EN) != 0) {
+ IoOr32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_EN_127_96), (UINT32) B_PCH_ACPI_GPE0_EN_127_96_LAN_WAKE);
+ }
+}
+
+/**
+ GbE Sx entry handler
+**/
+VOID
+PchLanSxCallback (
+ VOID
+ )
+{
+ if (IsGbeEnabled ()) {
+ GbeSxWorkaround ();
+ GbeConfigureDeepSxWake ();
+
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
new file mode 100644
index 0000000000..b4234f649c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
@@ -0,0 +1,464 @@
+/** @file
+ PCH Pcie SMM Driver Entry
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInitSmm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_DEVICE_OVERRIDE *mDevAspmOverride;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mNumOfDevAspmOverride;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPolicyRevision;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchBusNumber;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMin;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMax;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_ROOT_PORT_CONFIG mPcieRootPortConfig[PCH_MAX_PCIE_ROOT_PORTS];
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mLtrNonSupportRpBitMap;
+
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mPciePmTrapExecuted = FALSE;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAllowNoLtrIccPllShutdownPolicy = 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
+
+ @retval EFI_SUCCESS Root port complete successfully
+ @retval EFI_UNSUPPORTED PMC has invalid vendor ID
+**/
+EFI_STATUS
+PchPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ )
+{
+ UINT8 SecBus;
+ UINT8 SubBus;
+ EFI_HANDLE Handle;
+ UINT32 PwrmBase;
+ UINTN RpBase;
+ BOOLEAN LtrSupported;
+ BOOLEAN DownstreamDevicePresent;
+
+ Handle = NULL;
+ LtrSupported = TRUE;
+
+ RpBase = MmPciBase (
+ mPchBusNumber,
+ (UINT32) RpDevice,
+ (UINT32) RpFunction
+ );
+
+ if (MmioRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check for presence detect state
+ //
+ DownstreamDevicePresent = !!(MmioRead16 (RpBase + R_PCH_PCIE_SLSTS) & B_PCIE_SLSTS_PDS);
+
+ mLtrNonSupportRpBitMap &= ~(1 << PortIndex);
+
+ if (DownstreamDevicePresent) {
+ SecBus = MmioRead8 (RpBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ SubBus = MmioRead8 (RpBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ ASSERT (SecBus != 0 && SubBus != 0);
+ PchPcieInitRootPortDownstreamDevices (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ RpDevice,
+ RpFunction,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ (BOOLEAN)mPcieRootPortConfig[PortIndex].EnableCpm
+ );
+ if (!LtrSupported) {
+ mLtrNonSupportRpBitMap |= 1 << PortIndex;
+ }
+
+ //
+ // Perform Equalization
+ //
+ MmioOr32 (RpBase + R_PCH_PCIE_EX_LCTL3, B_PCIE_EX_LCTL3_PE);
+ MmioOr32 (RpBase + R_PCH_PCIE_LCTL, B_PCIE_LCTL_RL);
+ }
+
+ //
+ // If not all devices support LTR, set PWRMBASE + 0x3EC [24,16] = 0, 1
+ // This will disable ICC PLL shutdown
+ //
+ if (!mAllowNoLtrIccPllShutdownPolicy) {
+ PchPwrmBaseGet (&PwrmBase);
+ if (mLtrNonSupportRpBitMap != 0) {
+ MmioAndThenOr32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~BIT24, BIT16);
+ } else {
+ MmioAnd32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~(BIT24 | BIT16));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieSmiRpHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ PchPcieSmi (RpContext->RpIndex, RpContext->DevNum, RpContext->FuncNum);
+}
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ return;
+}
+
+/**
+ PCIE Link Equalization Request SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ ///
+ /// From PCI Express specification, the PCIe device can request for Link Equalization. When the
+ /// Link Equalization is requested by the device, an SMI will be generated by PCIe RP when
+ /// enabled and the SMI subroutine would invoke the Software Preset/Coefficient Search
+ /// software to re-equalize the link.
+ ///
+
+ return;
+
+}
+
+
+/**
+ An IoTrap callback to config PCIE power management settings
+**/
+VOID
+PchPciePmIoTrapSmiCallback (
+ VOID
+ )
+{
+ UINT32 PwrmBase;
+ UINT32 PortIndex;
+ UINTN RpBase;
+ BOOLEAN L1SubstatesSupportedPerPort;
+ UINT8 MaxPciePortNum;
+ UINTN RpDevice;
+ UINTN RpFunction;
+ PCH_GENERATION PchGen;
+ PCH_SERIES PchSeries;
+ PCH_STEPPING PchStep;
+
+ PchGen = GetPchGeneration ();
+ PchSeries = GetPchSeries ();
+ PchStep = PchStepping ();
+ L1SubstatesSupportedPerPort = FALSE;
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ //
+ // Step 4a
+ // In case not all devices support LTR, disable ICC PLL shutdown
+ // set PWRMBASE + 0x3EC [24,16] = 0, 1
+ // (Note this register should be saved and restored during S3 transitions)
+ //
+ if (!mAllowNoLtrIccPllShutdownPolicy) {
+ PchPwrmBaseGet (&PwrmBase);
+ MmioAndThenOr32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~BIT24, BIT16);
+ }
+
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction);
+ }
+ //
+ // Step 4b
+ // By this time, LTR support map is known.
+ // If all devices support LTR, allow ICC PLL shutdown
+ // (Note this register should be saved and restored during S3 transitions)
+ //
+ if (!mAllowNoLtrIccPllShutdownPolicy) {
+ if (mLtrNonSupportRpBitMap == 0) {
+ PchPwrmBaseGet (&PwrmBase);
+ MmioAnd32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~(BIT24 | BIT16));
+ }
+ }
+
+ //
+ // Program the remapped root port's ASPM based on endpoint's ASPM
+ //
+ if ((PchGen == SklPch) &&
+ (((PchSeries == PchLp) && (PchStep < PchLpC0)) ||
+ ((PchSeries == PchH) && (PchStep < PchHD0)))) {
+ return;
+ }
+}
+
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+PchPcieIoTrapSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_CONTEXT *CallbackContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ if (CallbackContext->WriteData == PciePmTrap) {
+ if (mPciePmTrapExecuted == FALSE) {
+ PchPciePmIoTrapSmiCallback ();
+ mPciePmTrapExecuted = TRUE;
+ }
+ } else {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ }
+}
+
+/**
+ This function clear the Io trap executed flag before enter S3
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+
+ @retval EFI_SUCCESS PCH register saved
+**/
+EFI_STATUS
+EFIAPI
+PchPcieS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ mPciePmTrapExecuted = FALSE;
+ return EFI_SUCCESS;
+}
+/**
+ Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
+
+ @param[in] ImageHandle The image handle of this module
+ @param[in] SystemTable The EFI System Table
+
+ @retval EFI_SUCCESS The function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+InitializePchPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 PortIndex;
+ UINT8 Data8;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINTN RpBase;
+ UINTN RpDevice;
+ UINTN RpFunction;
+ EFI_HANDLE PcieHandle;
+ PCH_PCIE_SMI_DISPATCH_PROTOCOL *PchPcieSmiDispatchProtocol;
+ EFI_HOB_GUID_TYPE* Hob;
+ UINT32 DevTableSize;
+ EFI_HANDLE PchIoTrapHandle;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT PchIoTrapContext;
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ PCH_PCIE_IOTRAP_PROTOCOL *PchPcieIoTrapProtocol;
+ EFI_HANDLE SxDispatchHandle;
+ UINT8 MaxPciePortNum;
+
+ DEBUG ((DEBUG_INFO, "InitializePchPcieSmm () Start\n"));
+
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ //
+ // Locate Pch Pcie Smi Dispatch Protocol
+ //
+ Status = gSmst->SmmLocateProtocol (&gPchPcieSmiDispatchProtocolGuid, NULL, (VOID**)&PchPcieSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ mPolicyRevision = mSiConfigHob->Header.Revision;
+ mPchBusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
+ mTempRootPortBusNumMin = mSiConfigHob->TempPciBusMin;
+ mTempRootPortBusNumMax = mSiConfigHob->TempPciBusMax;
+ mAllowNoLtrIccPllShutdownPolicy = (BOOLEAN) mPchConfigHob->PcieRp.AllowNoLtrIccPllShutdown;
+
+ ASSERT (sizeof mPcieRootPortConfig == sizeof mPchConfigHob->PcieRp.RootPort);
+ CopyMem (
+ mPcieRootPortConfig,
+ &(mPchConfigHob->PcieRp.RootPort),
+ sizeof (mPcieRootPortConfig)
+ );
+
+ mDevAspmOverride = NULL;
+ mNumOfDevAspmOverride = 0;
+ mLtrNonSupportRpBitMap = 0;
+
+ Hob = GetFirstGuidHob (&gPchDeviceTableHobGuid);
+ if (Hob != NULL) {
+ DevTableSize = GET_GUID_HOB_DATA_SIZE (Hob);
+ ASSERT ((DevTableSize % sizeof (PCH_PCIE_DEVICE_OVERRIDE)) == 0);
+ mNumOfDevAspmOverride = DevTableSize / sizeof (PCH_PCIE_DEVICE_OVERRIDE);
+ DEBUG ((DEBUG_INFO, "Found PcieDeviceTable HOB (%d entries)\n", mNumOfDevAspmOverride));
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ DevTableSize,
+ (VOID **) &mDevAspmOverride
+ );
+ CopyMem (mDevAspmOverride, GET_GUID_HOB_DATA (Hob), DevTableSize);
+ }
+
+ //
+ // Throught all PCIE root port function and register the SMI Handler for enabled ports.
+ //
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction);
+ //
+ // Skip the root port function which is not enabled
+ //
+ if (MmioRead32 (RpBase) == 0xFFFFFFFF) {
+ continue;
+ }
+
+ if (!mPcieRootPortConfig[PortIndex].EnableHotplugSmi) {
+ continue;
+ }
+ //
+ // Register SMI Handlers for Hot Plug and Link Active State Change
+ //
+ Data8 = MmioRead8 (RpBase + R_PCH_PCIE_SLCAP);
+ if (Data8 & B_PCIE_SLCAP_HPC) {
+ PcieHandle = NULL;
+ Status = PchPcieSmiDispatchProtocol->HotPlugRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieSmiRpHandlerFunction,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchPcieSmiDispatchProtocol->LinkActiveRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieLinkActiveStateChange,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Data32Or = B_PCH_PCIE_MPC_HPME;
+ Data32And = (UINT32) ~B_PCH_PCIE_MPC_HPME;
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (RpBase + R_PCH_PCIE_MPC),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+
+ //
+ // Register SMI Handler for Link Equalization Request from Gen 3 Devices.
+ //
+ Data8 = MmioRead8 (RpBase + R_PCH_PCIE_LCAP);
+ if ((Data8 & B_PCIE_LCAP_MLS) == V_PCIE_LCAP_MLS_GEN3) {
+ Status = PchPcieSmiDispatchProtocol->LinkEqRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieLinkEqHandlerFunction,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ PchIoTrapContext.Type = WriteTrap;
+ PchIoTrapContext.Length = 4;
+ PchIoTrapContext.Address = 0;
+ Status = mPchIoTrap->Register (
+ mPchIoTrap,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) PchPcieIoTrapSmiCallback,
+ &PchIoTrapContext,
+ &PchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the PCH Pcie IoTrap protocol
+ //
+ (gBS->AllocatePool) (EfiBootServicesData, sizeof (PCH_PCIE_IOTRAP_PROTOCOL), (VOID **)&PchPcieIoTrapProtocol);
+ PchPcieIoTrapProtocol->PcieTrapAddress = PchIoTrapContext.Address;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPchPcieIoTrapProtocolGuid,
+ PchPcieIoTrapProtocol,
+ NULL
+ );
+
+ //
+ // Register the callback for S3 entry
+ //
+ SxDispatchContext.Type = SxS3;
+ SxDispatchContext.Phase = SxEntry;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ PchPcieS3EntryCallBack,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "InitializePchPcieSmm () End\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c
new file mode 100644
index 0000000000..0717f38291
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c
@@ -0,0 +1,160 @@
+/** @file
+ PCH Port 61h bit-4 toggling in SMM IO Trap
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PchInitSmm.h"
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpu; ///< To read and write save state
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mPchIoTrapHandle; ///< Pause and resume via EFI_HANDLE
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *mPchSmmIoTrapControl; ///< To pause and resume IO trap
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mInternalState = 0; ///< To store the toggle value for each CPU threads
+
+/**
+ This SMI handle will pause the IO trap in the beginning
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+ @retval None
+**/
+VOID
+PchIoTrapPort61hSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *CallbackContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN CpuIndex;
+ UINTN Mask;
+ UINT8 ReadValue, WriteValue;
+ EFI_SMM_SAVE_STATE_IO_INFO IoInfo;
+ //
+ // Disabling the IO Trap, prevent SMI re-enter because of reading port 61h in handler itself
+ //
+ Status = mPchSmmIoTrapControl->Pause (
+ mPchSmmIoTrapControl,
+ mPchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Detects the CPU which causes the IO Trap
+ //
+ for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
+ Status = mSmmCpu->ReadSaveState (
+ mSmmCpu,
+ sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+ EFI_SMM_SAVE_STATE_REGISTER_IO,
+ CpuIndex,
+ &IoInfo
+ );
+ if (Status == EFI_SUCCESS) {
+ //
+ // Make sure the IO trap is byte read, port input only, and it is port 0x61
+ //
+ if ((IoInfo.IoWidth == EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8) &&
+ (IoInfo.IoType == EFI_SMM_SAVE_STATE_IO_TYPE_INPUT) &&
+ (IoInfo.IoPort == 0x61)) {
+ //
+ // Read from Port 61h, toggle bit4 based on the internal state
+ //
+ ReadValue = IoRead8 (0x61);
+ Mask = (UINTN) (1 << CpuIndex);
+ mInternalState ^= Mask;
+ WriteValue = (mInternalState & Mask) ? (ReadValue | 0x10) : (ReadValue & ~0x10);
+ Status = mSmmCpu->WriteSaveState (
+ mSmmCpu,
+ sizeof (UINT8),
+ EFI_SMM_SAVE_STATE_REGISTER_RAX,
+ CpuIndex,
+ &WriteValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ } //if the iotrap is the one we want
+ } //if iotrap happens for this thread
+ } //for (iterate for all threads)
+
+ //
+ // Resume the IO Trap
+ // Port 61h bit-4 emulation will be disabled after exit boot service
+ // The disabling mechanism is actually to not resume the trap.
+ // This means, even after exit boot service, this handler will be called once
+ // before it is disabled
+ //
+ if (mPchNvsArea->ExitBootServicesFlag == 0) {
+ Status = mPchSmmIoTrapControl->Resume (
+ mPchSmmIoTrapControl,
+ mPchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((DEBUG_INFO, "Port61H trap has been disabled. \n"));
+ }
+}
+
+
+/**
+ Locate required protocol and register the IO trap in this entry point
+
+ @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
+InstallIoTrapPort61h (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT PchIoTrapContext;
+
+ DEBUG ((DEBUG_INFO, "InstallIoTrapPort61h()\n"));
+
+ if (mPchConfigHob->Port61hSmm.Enable == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Locate the protocol to read and write save state
+ //
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Locate the protocol for pause and resume
+ //
+ Status = gSmst->SmmLocateProtocol (&gPchSmmIoTrapControlGuid, NULL, (VOID **) &mPchSmmIoTrapControl);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Configure trap type, in ECP, MergeDisable should be TRUE for pause and resume to work
+ //
+ PchIoTrapContext.Type = ReadTrap;
+ PchIoTrapContext.Length = 1;
+ PchIoTrapContext.Address = 0x61;
+ Status = mPchIoTrap->Register (
+ mPchIoTrap,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) PchIoTrapPort61hSmiCallback,
+ &PchIoTrapContext,
+ &mPchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
new file mode 100644
index 0000000000..463de1dba8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
@@ -0,0 +1,74 @@
+/** @file
+ PCH SPI Async SMI handler.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchInitSmm.h"
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMI_DISPATCH_PROTOCOL *mPchSmiDispatchProtocol;
+
+/**
+ This hardware SMI handler will be run every time the flash write/earse happens.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchSpiAsyncCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Dummy SMI handler
+ //
+}
+
+/**
+ This fuction install SPI ASYNC SMI handler.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpiAsyncSmiHandler (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ DEBUG ((DEBUG_INFO, "InstallPchSpiAsyncSmiHandler()\n"));
+
+ ///
+ /// Get the PCH SMM dispatch protocol
+ ///
+ mPchSmiDispatchProtocol = NULL;
+ Status = gSmst->SmmLocateProtocol (&gPchSmiDispatchProtocolGuid, NULL, (VOID **) &mPchSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register an SpiAsync callback function
+ ///
+ Handle = NULL;
+ Status = mPchSmiDispatchProtocol->SpiAsyncRegister (
+ mPchSmiDispatchProtocol,
+ PchSpiAsyncCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c
new file mode 100644
index 0000000000..f17b125d4f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c
@@ -0,0 +1,73 @@
+/** @file
+ PCH xHCI Sx handler implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/TimerLib.h>
+#include "PchInitSmm.h"
+
+/**
+ xHCI Controller Configurations Prior to Entering S3
+**/
+VOID
+PchXhciS3Callback (
+ VOID
+ )
+{
+ UINTN XhciPciMmBase;
+ UINT8 OrgCmdByte;
+ UINT16 OrgPmcs;
+ UINT32 OrgMmioAddr;
+ UINT32 OrgMmioHAddr;
+ UINT32 XhciMmioBase;
+
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ ///
+ /// Save Cmd and XhciBar and Pmcs registers
+ ///
+ OrgCmdByte = MmioRead8 (XhciPciMmBase + PCI_COMMAND_OFFSET);
+ OrgPmcs = MmioRead16 (XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS);
+ OrgMmioAddr = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & 0xFFFF0000;
+ OrgMmioHAddr = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4);
+
+ ///
+ /// Use the reserved MMIO
+ /// Clear MSE before changing MMIO address
+ ///
+ MmioAnd8 (XhciPciMmBase + PCI_COMMAND_OFFSET, (UINT8)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, (UINT32) mXhciMmioBaseAddr);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4, 0);
+
+ ///
+ /// Set MSE
+ ///
+ MmioOr8 (XhciPciMmBase + PCI_COMMAND_OFFSET, (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
+
+ XhciMmioBase = (UINT32) mXhciMmioBaseAddr;
+
+ ///
+ /// Restore Cmd and XhciBar and Pmcs registers
+ ///
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4, OrgMmioHAddr);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, OrgMmioAddr);
+ MmioWrite8 (XhciPciMmBase + PCI_COMMAND_OFFSET, OrgCmdByte);
+ ///
+ /// Bring device to D3
+ ///
+ MmioOr8 (XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS, (UINT8)(V_PCH_XHCI_PWR_CNTL_STS_PWR_STS_D3));
+
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c
new file mode 100644
index 0000000000..5c3ea07646
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c
@@ -0,0 +1,913 @@
+/** @file
+ Main implementation source file for the Io Trap SMM driver
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/PchNvs.h>
+
+#define GENERIC_IOTRAP_SIZE 0x100
+
+//
+// Module global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mDriverImageHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mIoTrapHandle;
+
+GLOBAL_REMOVE_IF_UNREFERENCED IO_TRAP_INSTANCE mIoTrapData;
+GLOBAL_REMOVE_IF_UNREFERENCED IO_TRAP_RECORD *mIoTrapRecord;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA *mPchNvsArea;
+
+
+static CONST UINT16 mLengthTable[10] = { 1, 2, 3, 4, 8, 16, 32, 64, 128, 256 };
+
+/**
+ Helper function that encapsulates IoTrap register access.
+ IO trap related register updates must be made in 2 registers, IOTRAP and DMI source decode.
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] Value value to be written in both registers
+ @param[in] SaveToBootscript if true, this register write will be saved to bootscript
+
+**/
+VOID
+SetIoTrapLowDword (
+ IN UINT8 TrapHandlerNum,
+ IN UINT32 Value,
+ IN BOOLEAN SaveToBootscript
+ )
+{
+ PchPcrWrite32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, Value);
+ PchPcrWrite32 (PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8, Value);
+ if (SaveToBootscript) {
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, 1, &Value);
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8, 1, &Value);
+ }
+}
+
+/**
+ Helper function that encapsulates IoTrap register access.
+ IO trap related register updates must be made in 2 registers, IOTRAP and DMI source decode.
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] Value value to be written in both registers
+ @param[in] SaveToBootscript if true, this register write will be saved to bootscript
+
+**/
+VOID
+SetIoTrapHighDword (
+ IN UINT8 TrapHandlerNum,
+ IN UINT32 Value,
+ IN BOOLEAN SaveToBootscript
+ )
+{
+ PchPcrWrite32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, Value);
+ PchPcrWrite32 (PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8 + 4, Value);
+ if (SaveToBootscript) {
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, 1, &Value);
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8 + 4, 1, &Value);
+ }
+}
+
+/**
+ IO resources allocated to IO traps need to be reported to OS so that they don't get reused.
+ This function makes IO trap allocation data available to ACPI
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] BaseAddress address of allocated IO resource
+ @param[in] Track TRUE = resource allocated, FALSE = resource freed
+
+**/
+VOID
+UpdateIoTrapAcpiResources (
+ IN UINT8 TrapHandlerNum,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN BOOLEAN Track
+ )
+{
+
+ if (Track == TRUE) {
+ mPchNvsArea->IoTrapAddress[TrapHandlerNum] = (UINT16) BaseAddress;
+ mPchNvsArea->IoTrapStatus[TrapHandlerNum] = 1;
+ } else {
+ mPchNvsArea->IoTrapStatus[TrapHandlerNum] = 0;
+ }
+}
+
+/**
+ Register a new IO Trap SMI dispatch function with a parent SMM driver.
+ The caller will provide information about the IO trap characteristics via
+ the context. This includes base address, length, read vs. r/w, etc.
+ This function will autoallocate IO base address from a common pool if the base address is 0,
+ and the RegisterContext Address field will be updated.
+ The service will not perform GCD allocation if the base address is non-zero.
+ In this case, the caller is responsible for the existence and allocation of the
+ specific IO range.
+ This function looks for the suitable handler and Register a new IoTrap handler
+ if the IO Trap handler is not used. It also enable the IO Trap Range to generate
+ SMI.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap SMI source for which the dispatch
+ function should be invoked. This may not be NULL.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record. This may not be NULL.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN OUT EFI_SMM_IO_TRAP_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS NextBaseAddress;
+ UINT32 NextUsedLength;
+ UINT8 NextTrapHandlerNum;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ UINT8 LengthIndex;
+ BOOLEAN TempMergeDisable;
+
+ //
+ // Return error if the type is invalid
+ //
+ if (RegisterContext->Type >= IoTrapTypeMaximum) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Type %0X is invalid! \n", RegisterContext->Type));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return error if the Length is invalid
+ //
+ if (RegisterContext->Length < 1 || RegisterContext->Length > GENERIC_IOTRAP_SIZE) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Length %0X is invalid! \n", RegisterContext->Length));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return error if the address is invalid
+ // PCH supports non-aligned address but (Address % 4 + Length) must not be more than 4
+ //
+ if (((RegisterContext->Length & (RegisterContext->Length - 1)) != 0) && (RegisterContext->Length != 3)) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Length is not power of 2 \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((RegisterContext->Length >= 4) && (RegisterContext->Address & 0x3)) ||
+ ((RegisterContext->Length < 4) && (((RegisterContext->Address & 0x3) + RegisterContext->Length) > 4))) {
+ DEBUG ((DEBUG_ERROR, "PCH does not support Dispatch Address %0X and Length %0X combination \n", RegisterContext->Address, RegisterContext->Length));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((RegisterContext->Length >= 4) && ((RegisterContext->Address & (RegisterContext->Length - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "Dispatch Address %0X is not aligned to the Length %0X \n", RegisterContext->Address, RegisterContext->Length));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (RegisterContext->Address) {
+ TempMergeDisable = TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+ //
+ // Loop through the first IO Trap handler, looking for the suitable handler
+ //
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // Get information from Io Trap handler register
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+
+ //
+ // Check if the IO Trap handler is not used
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) == 0) {
+ //
+ // Search available IO address and allocate it if the IO address is 0
+ //
+ BaseAddress = RegisterContext->Address;
+ if (BaseAddress == 0) {
+ //
+ // Allocate 256 byte range from GCD for common pool usage
+ //
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ BaseAddress = 0xFFFF;
+ }
+ Status = gDS->AllocateIoSpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdIoTypeIo,
+ 8,
+ GENERIC_IOTRAP_SIZE,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Can't find any available IO address! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RegisterContext->Address = (UINT16) BaseAddress;
+ UsedLength = GENERIC_IOTRAP_SIZE;
+ mIoTrapData.TrapUsedLength[TrapHandlerNum] = RegisterContext->Length;
+ mIoTrapData.TrackIoResource[TrapHandlerNum] = TRUE;
+ UpdateIoTrapAcpiResources (TrapHandlerNum, BaseAddress, TRUE);
+ } else {
+ BaseAddress &= B_PCH_PCR_PSTH_TRPREG_AD;
+ UsedLength = RegisterContext->Length;
+ }
+
+ //
+ // Register a new IoTrap handler
+ //
+ Status = PchInternalIoTrapSmiRegister (
+ IoTrapCallback,
+ TrapHandlerNum,
+ &mIoTrapHandle
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ mIoTrapData.IoTrapHandle[TrapHandlerNum] = mIoTrapHandle;
+ //
+ // Fill in the Length, address and Enable the IO Trap SMI
+ //
+ IoTrapRegLowDword = (UINT32) (((UsedLength - 1) & ~(BIT1 + BIT0)) << 16) |
+ (UINT16) BaseAddress |
+ B_PCH_PCR_PSTH_TRPREG_TSE;
+ if (UsedLength < 4) {
+ //
+ // The 4 bits is the Byte Enable Mask bits to indicate which byte that are trapped.
+ //
+ IoTrapRegHighDword = (((1 << UsedLength) - 1) << ((RegisterContext->Address & 0x3) + N_PCH_PCR_PSTH_TRPREG_BEM)) |
+ (UINT32) (RegisterContext->Type << N_PCH_PCR_PSTH_TRPREG_RWIO);
+ } else {
+ IoTrapRegHighDword = 0x000000F0 | (UINT32) (RegisterContext->Type << N_PCH_PCR_PSTH_TRPREG_RWIO);
+ }
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ //
+ // Set MergeDisable flag of the registered IoTrap
+ //
+ mIoTrapData.MergeDisable[TrapHandlerNum] = TempMergeDisable;
+ } else {
+ //
+ // Check next handler if MergeDisable is TRUE or the registered IoTrap if MergeDisable is TRUE
+ //
+ if ((TempMergeDisable == TRUE) || (mIoTrapData.MergeDisable[TrapHandlerNum] == TRUE)) {
+ continue;
+ }
+ //
+ // The IO Trap handler is used, calculate the Length
+ //
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ //
+ // Assign an addfress from common pool if the caller's address is 0
+ //
+ if (RegisterContext->Address == 0) {
+ //
+ // Check next handler if it's fully used
+ //
+ if (mIoTrapData.TrapUsedLength[TrapHandlerNum] >= GENERIC_IOTRAP_SIZE) {
+ continue;
+ }
+ //
+ // Check next handler if it's not for a common pool
+ //
+ if (UsedLength < GENERIC_IOTRAP_SIZE) {
+ continue;
+ }
+ //
+ // Check next handler if the size is too big
+ //
+ if (RegisterContext->Length >= (UINT16) GENERIC_IOTRAP_SIZE - mIoTrapData.TrapUsedLength[TrapHandlerNum]) {
+ continue;
+ }
+ //
+ // For common pool, we don't need to change the BaseAddress and UsedLength
+ //
+ RegisterContext->Address = (UINT16) (BaseAddress + mIoTrapData.TrapUsedLength[TrapHandlerNum]);
+ mIoTrapData.TrapUsedLength[TrapHandlerNum] += RegisterContext->Length;
+ } else {
+ //
+ // Check next handler if the address is smaller than the IO trap handler's start address
+ //
+ if (RegisterContext->Address < (UINT16) BaseAddress) {
+ continue;
+ }
+ //
+ // Check next handler if the max address is bigger than IO trap handler's range
+ //
+ if ((RegisterContext->Address + RegisterContext->Length) > (UINT16) (BaseAddress + 256)) {
+ continue;
+ }
+ //
+ // If this handler is used for common pool, assert if the caller's address is within the range
+ //
+ if (mIoTrapData.TrapUsedLength[TrapHandlerNum] != 0) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch address %0x is used for common pool! \n", RegisterContext->Address));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Calculate the Length which is maximum use address - start address
+ //
+ UsedLength = RegisterContext->Address + RegisterContext->Length - (UINT16) BaseAddress;
+ //
+ // Check the alignment is dword * power of 2 or not
+ //
+ for (LengthIndex = 0; LengthIndex < sizeof (mLengthTable) / sizeof (UINT16); LengthIndex++) {
+ if (UsedLength == mLengthTable[LengthIndex]) {
+ break;
+ }
+ }
+ //
+ // Check next handler if the alignment is not dword * power of 2
+ //
+ if (LengthIndex >= sizeof (mLengthTable) / sizeof (UINT16)) {
+ continue;
+ }
+
+ //
+ // Merge the overlap range: remove next Io Trap handler if next Io Trap handler's range is within this handler's range
+ //
+ for (NextTrapHandlerNum = TrapHandlerNum + 1; NextTrapHandlerNum != TrapHandlerNum; NextTrapHandlerNum++) {
+ //
+ // Check if NextTrapHandlerNum overflow
+ //
+ if (NextTrapHandlerNum >= IO_TRAP_HANDLER_NUM) {
+ NextTrapHandlerNum = 0;
+ }
+ //
+ // Get information from Io Trap handler register
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + NextTrapHandlerNum * 8, &IoTrapRegLowDword);
+ //
+ // Check next handler if the IO Trap handler is not used
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) == 0) {
+ continue;
+ }
+ //
+ // Check if next Io Trap handler's range is within this handler's range
+ //
+ NextUsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ NextBaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ if ((BaseAddress > NextBaseAddress) || ((BaseAddress + UsedLength) < (NextBaseAddress + NextUsedLength))) {
+ continue;
+ }
+ //
+ // Unregister the IO Trap handler
+ //
+ mIoTrapHandle = mIoTrapData.IoTrapHandle[NextTrapHandlerNum];
+ Status = PchInternalIoTrapSmiUnRegister (mIoTrapHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Clear the Io Trap handler register
+ //
+ SetIoTrapHighDword (NextTrapHandlerNum, 0, TRUE);
+ SetIoTrapLowDword (NextTrapHandlerNum, 0, TRUE);
+ }
+
+ ///
+ /// Update the Length
+ ///
+ IoTrapRegLowDword = (UINT32) (((UsedLength - 1) & ~(BIT1 + BIT0)) << 16) |
+ (UINT16) BaseAddress |
+ B_PCH_PCR_PSTH_TRPREG_TSE;
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ }
+ //
+ // Only set RWM bit when we need both read and write cycles.
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, &IoTrapRegHighDword);
+ if ((IoTrapRegHighDword & B_PCH_PCR_PSTH_TRPREG_RWM) == 0 &&
+ (UINT32) ((IoTrapRegHighDword & B_PCH_PCR_PSTH_TRPREG_RWIO) >> N_PCH_PCR_PSTH_TRPREG_RWIO) !=
+ (UINT32) RegisterContext->Type) {
+ IoTrapRegHighDword = ((IoTrapRegHighDword | B_PCH_PCR_PSTH_TRPREG_RWM) & ~B_PCH_PCR_PSTH_TRPREG_RWIO);
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ }
+ }
+ break;
+ }
+
+ if (TrapHandlerNum >= IO_TRAP_HANDLER_NUM) {
+ DEBUG ((DEBUG_ERROR, "All IO Trap handler is used, no available IO Trap handler! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Create database record and add to database
+ //
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (IO_TRAP_RECORD),
+ (VOID **) &mIoTrapRecord
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to allocate memory for mIoTrapRecord! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Gather information about the registration request
+ //
+ mIoTrapRecord->Signature = IO_TRAP_RECORD_SIGNATURE;
+ mIoTrapRecord->Context = *RegisterContext;
+ mIoTrapRecord->Callback = DispatchFunction;
+
+ InsertTailList (&mIoTrapData.CallbackDataBase, &mIoTrapRecord->Link);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&mIoTrapRecord->Link);
+
+ DEBUG ((DEBUG_INFO, "RegisterContext->Address:%x! \n", RegisterContext->Address));
+ DEBUG ((DEBUG_INFO, "RegisterContext->Length:%x! \n", RegisterContext->Length));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapUnRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ IO_TRAP_RECORD *RecordToDelete;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ UINT8 LengthIndex;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ RecordToDelete = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+ //
+ // Take the entry out of the linked list
+ //
+ if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Loop through the first IO Trap handler, looking for the suitable handler
+ //
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // Get information from Io Trap handler register
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+
+ //
+ // Check next Io Trap handler if the IO Trap handler is not used
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) == 0) {
+ continue;
+ }
+
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+
+ //
+ // Check if it's the maximum address of the Io Trap handler
+ //
+ if ((UINTN)(BaseAddress + UsedLength) == (UINTN)(RecordToDelete->Context.Address + RecordToDelete->Context.Length)) {
+
+ if (BaseAddress == RecordToDelete->Context.Address) {
+ //
+ // Disable the IO Trap handler if it's the only child of the Trap handler
+ //
+ mIoTrapHandle = mIoTrapData.IoTrapHandle[TrapHandlerNum];
+ Status = PchInternalIoTrapSmiUnRegister (mIoTrapHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ mIoTrapData.TrackIoResource[TrapHandlerNum] = FALSE;
+ //
+ // Clear the Io Trap handler register
+ //
+ IoTrapRegLowDword = 0;
+ IoTrapRegHighDword = 0;
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ if (mIoTrapData.TrackIoResource[TrapHandlerNum] == TRUE) {
+ mIoTrapData.TrackIoResource[TrapHandlerNum] = FALSE;
+ gDS->FreeIoSpace (BaseAddress, GENERIC_IOTRAP_SIZE);
+ UpdateIoTrapAcpiResources (TrapHandlerNum, BaseAddress, FALSE);
+ }
+
+ } else {
+ //
+ // Calculate the new IO Trap handler Length
+ //
+ UsedLength = UsedLength - RecordToDelete->Context.Length;
+ //
+ // Check the alignment is dword * power of 2 or not
+ //
+ for (LengthIndex = 0; LengthIndex < sizeof (mLengthTable) / sizeof (UINT16); LengthIndex++) {
+ if (UsedLength == mLengthTable[LengthIndex]) {
+ break;
+ }
+ }
+ //
+ // Do not decrease the length if the alignment is not dword * power of 2
+ //
+ if (LengthIndex >= sizeof (mLengthTable) / sizeof (UINT16)) {
+ break;
+ }
+ //
+ // Decrease the length to prevent the IO trap SMI
+ //
+ IoTrapRegLowDword = (UINT32) ((((UsedLength - 1) &~(BIT1 + BIT0)) << 16) | BaseAddress | B_PCH_PCR_PSTH_TRPREG_TSE);
+ }
+
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ break;
+ }
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+ Status = gSmst->SmmFreePool (RecordToDelete);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This I/O Trap SMI handler invokes the ACPI reference code to handle the SMI.
+ It currently assumes it owns all of the IO trap SMI.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+IoTrapCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT CurrentIoTrapRegisterData;
+ EFI_SMM_IO_TRAP_CONTEXT CurrentIoTrapContextData;
+ UINT16 BaseAddress;
+ UINT16 StartAddress;
+ UINT16 EndAddress;
+ UINT32 Data32;
+
+ if (!IsListEmpty (&mIoTrapData.CallbackDataBase)) {
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPC, &Data32);
+ BaseAddress = (UINT16) (Data32 & B_PCH_PCR_PSTH_TRPC_IOA);
+ StartAddress = (Data32 & B_PCH_PCR_PSTH_TRPC_AHBE) >> 16;
+ //
+ // StartAddress and EndAddress will be equal if it's byte access
+ //
+ EndAddress = (UINT16) (HighBitSet32 ((UINT32) (StartAddress))) + BaseAddress;
+ StartAddress = (UINT16) (LowBitSet32 ((UINT32) (StartAddress))) + BaseAddress;
+
+ CurrentIoTrapRegisterData.Type = (BOOLEAN) ((Data32 & B_PCH_PCR_PSTH_TRPC_RW) != 0);
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPD, &Data32);
+ CurrentIoTrapContextData.WriteData = Data32;
+ LinkInDb = GetFirstNode (&mIoTrapData.CallbackDataBase);
+
+ while (!IsNull (&mIoTrapData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = IO_TRAP_RECORD_FROM_LINK (LinkInDb);
+ if ((RecordInDb->Context.Address <= StartAddress) &&
+ (RecordInDb->Context.Address + RecordInDb->Context.Length > EndAddress)) {
+ if (RecordInDb->Context.Type == ReadWriteTrap || RecordInDb->Context.Type == CurrentIoTrapRegisterData.Type) {
+ //
+ // Pass the IO trap context information
+ //
+ RecordInDb->Callback (&RecordInDb->Link, &CurrentIoTrapContextData,NULL,NULL);
+ }
+ //
+ // Break if the address is match
+ //
+ break;
+ } else {
+ LinkInDb = GetNextNode (&mIoTrapData.CallbackDataBase, &RecordInDb->Link);
+ if (IsNull (&mIoTrapData.CallbackDataBase, LinkInDb)) {
+ //
+ // An IO access was trapped that does not have a handler registered.
+ // This indicates an error condition.
+ //
+ ASSERT (FALSE);
+ }
+ }
+ }
+ }
+}
+
+/**
+ Pause IoTrap callback function.
+
+ This function disables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlPause (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *IoTrapRecord;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ BOOLEAN TempMergeDisable;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoTrapRecord = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+
+ if (IoTrapRecord->Context.Address) {
+ TempMergeDisable =TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+
+ if ((IoTrapRecord->Signature != IO_TRAP_RECORD_SIGNATURE) ||
+ (TempMergeDisable != TRUE) ||
+ (IoTrapRecord->Context.Address == 0) ||
+ (IoTrapRecord->Context.Length == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // This IoTrap register should be merge disabled.
+ //
+ if (mIoTrapData.MergeDisable[TrapHandlerNum] != TRUE) {
+ continue;
+ }
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, &IoTrapRegHighDword);
+ //
+ // Depending on the usage, we will obtain the UsedLength and BaseAddress differently
+ // If the registered trap length is less than 4, we obtain the length from Byte Enable Mask
+ // In the other hand, we obtain the length from Address Mask
+ //
+ if ((IoTrapRegHighDword & 0xF0) != 0xF0) {
+ UsedLength = (UINT32) (HighBitSet32 (IoTrapRegHighDword & 0xF0) - LowBitSet32 (IoTrapRegHighDword & 0xF0) + 1);
+ BaseAddress = (IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) + LowBitSet32 ((IoTrapRegHighDword & 0xF0) >> 4);
+ } else {
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ }
+
+ //
+ // The address and length of record matches the IoTrap register's.
+ //
+ if ((BaseAddress == IoTrapRecord->Context.Address) &&
+ (UsedLength == IoTrapRecord->Context.Length )) {
+ //
+ // Check if status matched.
+ // If this is already Paused, return warning status.
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_TSE) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Clear IoTrap register SMI enable bit
+ //
+ IoTrapRegLowDword &= (~B_PCH_PCR_PSTH_TRPREG_TSE);
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, FALSE);
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Resume IoTrap callback function.
+
+ This function enables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady RESUMED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlResume (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *IoTrapRecord;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ BOOLEAN TempMergeDisable;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ IoTrapRecord = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+
+ if (IoTrapRecord->Context.Address) {
+ TempMergeDisable = TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+
+ if ((IoTrapRecord->Signature != IO_TRAP_RECORD_SIGNATURE) ||
+ (TempMergeDisable != TRUE) ||
+ (IoTrapRecord->Context.Address == 0) ||
+ (IoTrapRecord->Context.Length == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // This IoTrap register should be merge disabled.
+ //
+ if (mIoTrapData.MergeDisable[TrapHandlerNum] != TRUE) {
+ continue;
+ }
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, &IoTrapRegHighDword);
+ //
+ // Depending on the usage, we will obtain the UsedLength and BaseAddress differently
+ // If the registered trap length is less than 4, we obtain the length from Byte Enable Mask
+ // In the other hand, we obtain the length from Address Mask
+ //
+ if ((IoTrapRegHighDword & 0xF0) != 0xF0) {
+ UsedLength = (UINT32) (HighBitSet32 (IoTrapRegHighDword & 0xF0) - LowBitSet32 (IoTrapRegHighDword & 0xF0) + 1);
+ BaseAddress = (IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) + LowBitSet32 ((IoTrapRegHighDword & 0xF0) >> 4);
+ } else {
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ }
+
+ //
+ // The address and length of record matches the IoTrap register's.
+ //
+ if ((BaseAddress == IoTrapRecord->Context.Address) &&
+ (UsedLength == IoTrapRecord->Context.Length )) {
+ //
+ // Check if status matched.
+ // If this is already Resume, return warning status.
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_TSE) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Set IoTrap register SMI enable bit
+ //
+ IoTrapRegLowDword |= (B_PCH_PCR_PSTH_TRPREG_TSE);
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, FALSE);
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ The IoTrap module abstracts PCH I/O trapping capabilities for other drivers.
+ This driver manages the limited I/O trap resources.
+
+ @param[in] ImageHandle Image handle for this driver image
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallIoTrap (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+
+
+ //
+ // Initialize the EFI SMM driver library
+ //
+ mDriverImageHandle = ImageHandle;
+
+ //
+ // Initialize the IO TRAP protocol we produce
+ //
+ mIoTrapData.Signature = IO_TRAP_INSTANCE_SIGNATURE;
+ mIoTrapData.EfiSmmIoTrapDispatchProtocol.Register = IoTrapRegister;
+ mIoTrapData.EfiSmmIoTrapDispatchProtocol.UnRegister = IoTrapUnRegister;
+
+ //
+ // Initialize the IO TRAP control protocol.
+ //
+ mIoTrapData.PchSmmIoTrapControlProtocol.Pause = IoTrapControlPause;
+ mIoTrapData.PchSmmIoTrapControlProtocol.Resume = IoTrapControlResume;
+
+ //
+ // Initialize IO TRAP Callback DataBase
+ //
+ InitializeListHead (&mIoTrapData.CallbackDataBase);
+
+ //
+ // Get address of PchNvs structure for later use
+ //
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPchNvsArea = PchNvsAreaProtocol->Area;
+
+ //
+ // Install protocol interface
+ //
+ mIoTrapData.Handle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mIoTrapData.Handle,
+ &gEfiSmmIoTrapDispatch2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIoTrapData.EfiSmmIoTrapDispatchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mIoTrapData.Handle,
+ &gPchSmmIoTrapControlGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIoTrapData.PchSmmIoTrapControlProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h
new file mode 100644
index 0000000000..99bb3527f7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h
@@ -0,0 +1,193 @@
+/** @file
+ Defines and prototypes for the IoTrap SMM driver
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _IO_TRAP_H_
+#define _IO_TRAP_H_
+
+//
+// Include files
+//
+#include <Library/S3BootScriptLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Protocol/PchSmmIoTrapControl.h>
+#define IO_TRAP_HANDLER_NUM 4
+
+//
+// Driver private data
+//
+#define IO_TRAP_INSTANCE_SIGNATURE SIGNATURE_32 ('I', 'O', 'T', 'P')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL EfiSmmIoTrapDispatchProtocol;
+ EFI_HANDLE IoTrapHandle[IO_TRAP_HANDLER_NUM];
+ LIST_ENTRY CallbackDataBase;
+ UINT32 TrapUsedLength[IO_TRAP_HANDLER_NUM];
+ BOOLEAN MergeDisable[IO_TRAP_HANDLER_NUM]; ///< Determine if IoTrap can be merged with other IoTrap
+ PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PchSmmIoTrapControlProtocol; ///< Protocol for runtime control the IoTrap state
+ BOOLEAN TrackIoResource[IO_TRAP_HANDLER_NUM];
+} IO_TRAP_INSTANCE;
+
+#define IO_TRAP_INSTANCE_FROM_THIS(a) CR (a, IO_TRAP_INSTANCE, EfiSmmIoTrapDispatchProtocol, IO_TRAP_INSTANCE_SIGNATURE)
+
+///
+/// "IOTRAP" RECORD
+/// Linked list data structures
+///
+#define IO_TRAP_RECORD_SIGNATURE SIGNATURE_32 ('I', 'T', 'R', 'C')
+
+typedef struct _IO_TRAP_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT Context;
+ EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
+} IO_TRAP_RECORD;
+
+#define IO_TRAP_RECORD_FROM_LINK(_record) CR (_record, IO_TRAP_RECORD, Link, IO_TRAP_RECORD_SIGNATURE)
+
+//
+// Prototypes
+//
+/**
+ The IoTrap module abstracts PCH I/O trapping capabilities for other drivers.
+ This driver manages the limited I/O trap resources.
+
+ @param[in] ImageHandle Image handle for this driver image
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallIoTrap (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Register a new IO Trap SMI dispatch function with a parent SMM driver.
+ The caller will provide information about the IO trap characteristics via
+ the context. This includes base address, length, read vs. r/w, etc.
+ This function will autoallocate IO base address from a common pool if the base address is 0,
+ and the RegisterContext Address field will be updated.
+ The service will not perform GCD allocation if the base address is non-zero.
+ In this case, the caller is responsible for the existence and allocation of the
+ specific IO range.
+ This function looks for the suitable handler and Register a new IoTrap handler
+ if the IO Trap handler is not used. It also enable the IO Trap Range to generate
+ SMI.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap SMI source for which the dispatch
+ function should be invoked. This may not be NULL.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record. This may not be NULL.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN OUT EFI_SMM_IO_TRAP_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapUnRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ This I/O Trap SMI handler invokes the ACPI reference code to handle the SMI.
+ It currently assumes it owns all of the IO trap SMI.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+IoTrapCallback (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Pause IoTrap callback function.
+
+ This function disables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlPause (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Resume IoTrap callback function.
+
+ This function enables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady RESUMED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlResume (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
new file mode 100644
index 0000000000..24773560e5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
@@ -0,0 +1,2497 @@
+/** @file
+ This function handle the register/unregister of PCH specific SMI events.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+
+/**
+ The internal function used to create and insert a database record
+ for SMI record of Pch Smi types.
+
+ @param[in] SrcDesc The pointer to the SMI source description
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] PchSmiType Specific SMI type of PCH SMI
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc,
+ IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+ PCH_SMM_SOURCE_DESC NullSourceDesc;
+
+ //
+ // Initialize NullSourceDesc
+ //
+ NullInitSourceDesc (&NullSourceDesc);
+
+ if (CompareSources (SrcDesc, &NullSourceDesc)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SetMem (Record, sizeof (DATABASE_RECORD), 0);
+ //
+ // Gather information about the registration request
+ //
+ Record->Signature = DATABASE_RECORD_SIGNATURE;
+ Record->PchSmiCallback = DispatchFunction;
+ Record->ProtocolType = PchSmiDispatchType;
+ Record->PchSmiType = PchSmiType;
+
+ Record->ContextFunctions.GetContext = NULL;
+ Record->ContextFunctions.CmpContext = NULL;
+ Record->ContextFunctions.GetCommBuffer = NULL;
+ Record->ClearSource = NULL;
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+
+ //
+ // After ensuring the source of event is not null, we will insert the record into the database
+ //
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+}
+
+
+//
+// TCO_STS bit that needs to be cleared
+//
+PCH_SMM_SOURCE_DESC mDescSrcTcoSts = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+ },
+ NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+ Clear the TCO SMI status bit and block after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmClearSourceAndBlock (SrcDesc);
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Clear the TCO SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmClearSource (SrcDesc);
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Initialize Source descriptor structure
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+NullInitSourceDesc (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ ZeroMem (SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+ SrcDesc->En[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->En[1].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->Sts[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->PmcSmiSts.Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+}
+
+//
+// Mch srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescMch = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_DMISMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of MCH event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiMchRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescMch,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiMchType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// TcoTimeout srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_TIMEOUT
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of TcoTimeout event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiTcoTimeoutRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescTcoTimeout,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiTcoTimeoutType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// OsTco srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescOsTco = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_SW_TCO_SMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of OS TCO event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiOsTcoRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescOsTco,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiOsTcoType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// Nmi
+//
+PCH_SMM_SOURCE_DESC mSrcDescNmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_CNT}
+ },
+ S_PCH_TCO1_CNT,
+ N_PCH_TCO_CNT_NMI2SMI_EN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NMI2SMI
+ }
+ },
+ //
+ // NOTE: The status of NMI2SMI won't reflect to PMC SMI_STS.
+ // So skip the top level status check and check the TCO1_STS directly.
+ //
+ NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+ The register function used to register SMI handler of NMI event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNmiRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescNmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiNmiType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// IntruderDetect srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO2_CNT}
+ },
+ S_PCH_TCO2_CNT,
+ N_PCH_TCO2_CNT_INTRD_SEL
+ }
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO2_STS}
+ },
+ S_PCH_TCO2_STS,
+ N_PCH_TCO2_STS_INTRD_DET
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of Intruder Detect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiIntruderDetRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescIntruderDet,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiIntruderDetectType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// SpiBiosWp srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_BLE
+ },
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_SYNC_SS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ Special handling for SPI Write Protect
+
+ @param[in] SrcDesc Not used
+**/
+VOID
+EFIAPI
+PchTcoSpiWpClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN SpiRegBase;
+
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ MmioAndThenOr32 (
+ SpiRegBase + R_PCH_SPI_BC,
+ (UINT32) ~B_PCH_SPI_BC_ASYNC_SS,
+ B_PCH_SPI_BC_SYNC_SS
+ );
+
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Special handling to enable SPI Write Protect
+**/
+VOID
+PchTcoSpiWpEnableSource (
+ VOID
+ )
+{
+ UINTN SpiRegBase;
+
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ MmioAndThenOr32 (
+ SpiRegBase + R_PCH_SPI_BC,
+ (UINT32) ~(B_PCH_SPI_BC_ASYNC_SS | B_PCH_SPI_BC_SYNC_SS),
+ B_PCH_SPI_BC_LE
+ );
+
+ IoOr32 (mAcpiBaseAddr + R_PCH_SMI_EN, B_PCH_SMI_EN_TCO);
+
+ //
+ // Clear the source
+ //
+ PchTcoSpiWpClearSource (NULL);
+}
+
+/**
+ The register function used to register SMI handler of BIOS write protect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiSpiBiosWpRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSpiBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiSpiBiosWpType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSpiWpClearSource;
+ PchTcoSpiWpClearSource (NULL);
+ PchTcoSpiWpEnableSource ();
+ }
+ return Status;
+}
+
+//
+// LpcBiosWp srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_LPC_BC
+ ) }
+ },
+ S_PCH_LPC_BC,
+ N_PCH_LPC_BC_LE
+ }
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_BIOSWR
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of LPC BIOS write protect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiLpcBiosWpRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescLpcBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiLpcBiosWpType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// NEWCENTURY_STS bit that needs to be cleared
+//
+PCH_SMM_SOURCE_DESC mSrcDescNewCentury = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NEWCENTURY
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ Check and clear NEWCENTURY_STS.
+ It will clear the SMI status once it happens.
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+**/
+VOID
+EFIAPI
+PchTcoClearNewCenturySts (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINT16 TcoSts1;
+ TcoSts1 = IoRead16 (mTcoBaseAddr + R_PCH_TCO1_STS);
+
+ if (TcoSts1 & B_PCH_TCO1_STS_NEWCENTURY) {
+ PchTcoSmiClearSourceAndBlock (&mSrcDescNewCentury);
+ }
+}
+
+/**
+ The register function used to register SMI handler of NEW CENTURY event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNewCenturyRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescNewCentury,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiNewCenturyType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoClearNewCenturySts;
+ PchTcoClearNewCenturySts (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiUnRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *Record;
+
+ Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == PCI_DEVICE_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_PCH_SPI_BC) &&
+ (Record->SrcDesc.En[1].Bit == N_PCH_SPI_BC_BLE)) {
+ //
+ // SPI Write Protect cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ } else if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == PCI_DEVICE_NUMBER_PCH_LPC) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_LPC) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_PCH_LPC_BC) &&
+ (Record->SrcDesc.En[1].Bit == N_PCH_LPC_BC_LE)) {
+ //
+ // eSPI/LPC Write Protect cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ }
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+
+//
+// PcieRpHotPlug srcdesc
+//
+PCH_SMM_SOURCE_DESC PchPcieSmiRpHotPlugTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_MPC}
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_SMSCS}
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP hotplug event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Indicate the RP index (0-based)
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiHotPlugRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN RpDev;
+ UINTN RpFun;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPchPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+ //
+ // Patch the RP device number and function number of srcdesc.
+ //
+ PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ Status = PchSmiRecordInsert (
+ &PchPcieSmiRpHotPlugTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpHotplugType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&PchPcieSmiRpHotPlugTemplate);
+ PchSmmEnableSource (&PchPcieSmiRpHotPlugTemplate);
+
+ return Status;
+}
+
+//
+// PcieRpLinkActive srcdesc
+//
+PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkActiveTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_MPC}
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_SMSCS}
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP link active event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Indicate the RP index (0-based)
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiLinkActiveRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN RpDev;
+ UINTN RpFun;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPchPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+ //
+ // Patch the RP device number and function number of srcdesc.
+ //
+ PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ Status = PchSmiRecordInsert (
+ &PchPcieSmiRpLinkActiveTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpLinkActiveType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&PchPcieSmiRpLinkActiveTemplate);
+ PchSmmEnableSource (&PchPcieSmiRpLinkActiveTemplate);
+
+ return Status;
+}
+
+//
+// PcieRpLinkEq srcdesc
+//
+PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkEqTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_EQCFG1}
+ },
+ S_PCH_PCIE_EQCFG1,
+ N_PCH_PCIE_EQCFG1_LERSMIE
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_SMSCS}
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_LERSMIS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP Link Equalization Request event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Indicate the RP index (0-based)
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiLinkEqRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ UINTN RpDev;
+ UINTN RpFun;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPchPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+ //
+ // Patch the RP device number and function number of srcdesc.
+ //
+ PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ return PchSmiRecordInsert (
+ &PchPcieSmiRpLinkEqTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpLinkEqType,
+ DispatchHandle
+ );
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiUnRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+//
+// Pme srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescPme = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_EN_127_96}
+ },
+ S_PCH_ACPI_GPE0_EN_127_96,
+ N_PCH_ACPI_GPE0_EN_127_96_PME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_STS_127_96}
+ },
+ S_PCH_ACPI_GPE0_STS_127_96,
+ N_PCH_ACPI_GPE0_STS_127_96_PME
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPE0
+ }
+};
+
+/**
+ The register function used to register SMI handler of PME event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescPme,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiPmeType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescPme);
+ PchSmmEnableSource (&mSrcDescPme);
+
+ return Status;
+}
+
+//
+// PmeB0 srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_EN_127_96}
+ },
+ S_PCH_ACPI_GPE0_EN_127_96,
+ N_PCH_ACPI_GPE0_EN_127_96_PME_B0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_STS_127_96}
+ },
+ S_PCH_ACPI_GPE0_STS_127_96,
+ N_PCH_ACPI_GPE0_STS_127_96_PME_B0
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPE0
+ }
+};
+
+/**
+ The register function used to register SMI handler of PME B0 event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeB0Register (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescPmeB0,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiPmeB0Type,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescPmeB0);
+ PchSmmEnableSource (&mSrcDescPmeB0);
+
+ return Status;
+}
+
+//
+// RtcAlarm srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_EN}
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_RTC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_STS}
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_RTC
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ The register function used to register SMI handler of RTC alarm event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiRtcAlarmRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescRtcAlarm,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiRtcAlarmType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescRtcAlarm);
+ PchSmmEnableSource (&mSrcDescRtcAlarm);
+
+ return Status;
+}
+
+//
+// TmrOverflow srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_EN}
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_TMROF
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_STS}
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_TMROF
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ The register function used to register SMI handler of Timer Overflow event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiTmrOverflowRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescTmrOverflow,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiTmrOverflowType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescTmrOverflow);
+ PchSmmEnableSource (&mSrcDescTmrOverflow);
+
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiUnRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+//
+// GpioUnlock srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescGpioUnlock = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_GPIO_UNLOCK
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPIO_UNLOCK
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPIO_UNLOCK
+ }
+};
+
+/**
+ The register function used to register SMI handler of GPIO Unlock event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchGpioUnlockSmiRegister (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescGpioUnlock,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchGpioUnlockSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescGpioUnlock);
+ PchSmmEnableSource (&mSrcDescGpioUnlock);
+
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent GPIO UNLOCK SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchGpioUnlockSmiUnRegister (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+//
+// SerialIrq srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SERIRQ
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SERIRQ
+ }
+};
+
+/**
+ The register function used to register SMI handler of Serial IRQ event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSerialIrqRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSerialIrq,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSerialIrqType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescSerialIrq);
+ PchSmmEnableSource (&mSrcDescSerialIrq);
+
+ return Status;
+}
+
+//
+// McSmi srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescMcSmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_MCSMI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MCSMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MCSMI
+ }
+};
+
+/**
+ The register function used to register SMI handler of MCSMI event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiMcSmiRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescMcSmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiMcSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescMcSmi);
+ PchSmmEnableSource (&mSrcDescMcSmi);
+
+ return Status;
+}
+
+//
+// SmBus srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSmbus = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SMBUS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SMBUS
+ }
+};
+
+/**
+ The register function used to register SMI handler of SMBUS event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSmbusRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSmbus,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSmBusType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescSmbus);
+ PchSmmEnableSource (&mSrcDescSmbus);
+
+ return Status;
+}
+
+//
+// SpiAsyncSmi srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_ASE_BWP
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_ASYNC_SS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SPI
+ }
+};
+
+/**
+ Special handling for SPI Asynchronous SMI.
+ If SPI ASYNC SMI is enabled, De-assert SMI is sent when Flash Cycle Done
+ transitions from 1 to 0 or when the SMI enable becomes false.
+
+ @param[in] SrcDesc Not used
+**/
+VOID
+EFIAPI
+PchSmiSpiAsyncClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN SpiRegBase;
+ UINT32 SpiBar0;
+
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ SpiBar0 = MmioRead32 (SpiRegBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+ if (SpiBar0 != PCH_SPI_BASE_ADDRESS) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ SpiBar0 = PCH_SPI_BASE_ADDRESS;
+ MmioAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (SpiRegBase + R_PCH_SPI_BAR0, SpiBar0);
+ MmioOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ MmioOr32 (SpiBar0 + R_PCH_SPI_HSFSC, B_PCH_SPI_HSFSC_FDONE);
+}
+
+/**
+ Special handling to enable SPI Asynchronous SMI
+**/
+VOID
+PchSmiSpiAsyncEnableSource (
+ VOID
+ )
+{
+ UINTN SpiRegBase;
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ MmioAndThenOr32 (
+ SpiRegBase + R_PCH_SPI_BC,
+ (UINT32) ~B_PCH_SPI_BC_SYNC_SS,
+ B_PCH_SPI_BC_ASE_BWP
+ );
+
+ //
+ // Clear the source
+ //
+ PchSmiSpiAsyncClearSource (NULL);
+}
+
+/**
+ The register function used to register SMI handler of SPI Asynchronous event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSpiAsyncRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSpiAsyncSmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSpiAsyncType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchSmiSpiAsyncClearSource;
+ PchSmiSpiAsyncClearSource (NULL);
+ PchSmiSpiAsyncEnableSource ();
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED Return access denied since SPI aync SMI handler is not able to disabled.
+**/
+EFI_STATUS
+EFIAPI
+PchSmiUnRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *Record;
+ UINTN SpiRegBase;
+
+ Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if ((Record->SrcDesc.En[0].Reg.Type == PCIE_ADDR_TYPE) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev == PCI_DEVICE_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_PCH_SPI_BC) &&
+ (Record->SrcDesc.En[0].Bit == N_PCH_SPI_BC_ASE_BWP)) {
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ if (MmioRead8 (SpiRegBase + R_PCH_SPI_BC) & B_PCH_SPI_BC_BILD) {
+ //
+ // SPI Asynchronous SMI cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+
+/**
+ Declaration of PCH TCO SMI DISPATCH PROTOCOL instance
+**/
+PCH_TCO_SMI_DISPATCH_PROTOCOL mPchTcoSmiDispatchProtocol = {
+ PCH_TCO_SMI_DISPATCH_REVISION, // Revision
+ PchTcoSmiUnRegister, // Unregister
+ PchTcoSmiMchRegister, // Mch
+ PchTcoSmiTcoTimeoutRegister, // TcoTimeout
+ PchTcoSmiOsTcoRegister, // OsTco
+ PchTcoSmiNmiRegister, // Nmi
+ PchTcoSmiIntruderDetRegister, // IntruderDectect
+ PchTcoSmiSpiBiosWpRegister, // SpiBiosWp
+ PchTcoSmiLpcBiosWpRegister, // LpcBiosWp
+ PchTcoSmiNewCenturyRegister // NewCentury
+};
+
+/**
+ Declaration of PCH PCIE SMI DISPATCH PROTOCOL instance
+**/
+PCH_PCIE_SMI_DISPATCH_PROTOCOL mPchPcieSmiDispatchProtocol = {
+ PCH_PCIE_SMI_DISPATCH_REVISION, // Revision
+ PchPcieSmiUnRegister, // Unregister
+ PchPcieSmiHotPlugRegister, // PcieRpXHotPlug
+ PchPcieSmiLinkActiveRegister, // PcieRpXLinkActive
+ PchPcieSmiLinkEqRegister // PcieRpXLinkEq
+};
+
+/**
+ Declaration of PCH ACPI SMI DISPATCH PROTOCOL instance
+**/
+PCH_ACPI_SMI_DISPATCH_PROTOCOL mPchAcpiSmiDispatchProtocol = {
+ PCH_ACPI_SMI_DISPATCH_REVISION, // Revision
+ PchAcpiSmiUnRegister, // Unregister
+ PchAcpiSmiPmeRegister, // Pme
+ PchAcpiSmiPmeB0Register, // PmeB0
+ PchAcpiSmiRtcAlarmRegister, // RtcAlarm
+ PchAcpiSmiTmrOverflowRegister // TmrOverflow
+};
+
+/**
+ Declaration of PCH GPIO UNLOCK SMI DISPATCH PROTOCOL instance
+**/
+PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL mPchGpioUnlockSmiDispatchProtocol = {
+ PCH_GPIO_UNLOCK_SMI_DISPATCH_REVISION,// Revision
+ PchGpioUnlockSmiUnRegister, // Unregister
+ PchGpioUnlockSmiRegister // GpioUnlock
+};
+
+/**
+ Declaration of MISC PCH SMI DISPATCH PROTOCOL instance
+**/
+PCH_SMI_DISPATCH_PROTOCOL mPchSmiDispatchProtocol = {
+ PCH_SMI_DISPATCH_REVISION, // Revision
+ PchSmiUnRegister, // Unregister
+ PchSmiSerialIrqRegister, // SerialIrq
+ PchSmiMcSmiRegister, // McSmi
+ PchSmiSmbusRegister, // SmBus
+ PchSmiSpiAsyncRegister // SpiAsync
+};
+
+/**
+ Install protocols of PCH specifics SMI types, including
+ PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+ @retval the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ Handle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchTcoSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchTcoSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchPcieSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchPcieSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchAcpiSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchAcpiSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchGpioUnlockSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchGpioUnlockSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchSmiDispatchProtocol
+ );
+
+ return Status;
+}
+
+/**
+ The function to dispatch all callback function of PCH SMI types.
+
+ @retval EFI_SUCCESS Function successfully completed
+ @retval EFI_UNSUPPORTED no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+ IN DATABASE_RECORD *Record
+ )
+{
+ EFI_STATUS Status;
+ PCH_SMI_TYPES PchSmiType;
+ UINTN RpIndex;
+ PCH_PCIE_SMI_RP_CONTEXT RpContext;
+
+ PchSmiType = Record->PchSmiType;
+ Status = EFI_SUCCESS;
+
+ switch (PchSmiType) {
+ case PchTcoSmiMchType:
+ case PchTcoSmiTcoTimeoutType:
+ case PchTcoSmiOsTcoType:
+ case PchTcoSmiNmiType:
+ case PchTcoSmiIntruderDetectType:
+ case PchTcoSmiSpiBiosWpType:
+ case PchTcoSmiLpcBiosWpType:
+ case PchTcoSmiNewCenturyType:
+ ((PCH_TCO_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchPcieSmiRpHotplugType:
+ case PchPcieSmiRpLinkActiveType:
+ case PchPcieSmiRpLinkEqType:
+ RpContext.BusNum = DEFAULT_PCI_BUS_NUMBER_PCH;
+ RpContext.DevNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev;
+ RpContext.FuncNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc;
+ GetPchPcieRpNumber (RpContext.DevNum, RpContext.FuncNum, &RpIndex);
+ RpContext.RpIndex = (UINT8) RpIndex;
+ ((PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link, &RpContext);
+ break;
+ case PchAcpiSmiPmeType:
+ case PchAcpiSmiPmeB0Type:
+ case PchAcpiSmiRtcAlarmType:
+ case PchAcpiSmiTmrOverflowType:
+ ((PCH_ACPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchGpioUnlockSmiType:
+ ((PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchEspiSmiEspiSlaveType:
+ ((PCH_ESPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchSmiSerialIrqType:
+ case PchSmiMcSmiType:
+ case PchSmiSmBusType:
+ case PchSmiSpiAsyncType:
+ case PchIoTrapSmiType: ///< internal type for IoTrap
+ ((PCH_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+PCH_SMM_SOURCE_DESC mSrcDescIoTrap[4] = {
+ //
+ // PCH I/O Trap register 0 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 0
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 1 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG1) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 1
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 2 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG2) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 2
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 3 monitor,
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG3) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 3
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ }
+};
+
+/**
+ The register function used to register SMI handler of IoTrap event.
+ This is internal function and only used by Iotrap module.
+
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] IoTrapIndex Index number of IOTRAP register
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN IoTrapIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescIoTrap[IoTrapIndex],
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchIoTrapSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescIoTrap[IoTrapIndex]);
+ PchSmmEnableSource (&mSrcDescIoTrap[IoTrapIndex]);
+
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
new file mode 100644
index 0000000000..b6fc2b95fd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
@@ -0,0 +1,113 @@
+## @file
+# Component description file for the Pch SMI Dispatch Handlers module
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchSmiDispatcher
+FILE_GUID = B0D6ED53-B844-43f5-BD2F-61095264E77E
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InitializePchSmmDispatcher
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+IoLib
+DebugLib
+PcdLib
+BaseLib
+BaseMemoryLib
+HobLib
+DevicePathLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchPcrLib
+SmmServicesTableLib
+ReportStatusCodeLib
+PerformanceLib
+DxeServicesTableLib
+GpioLib
+GpioPrivateLib
+S3BootScriptLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+# Progress Code for S3 Suspend end.
+# PROGRESS_CODE_S3_SUSPEND_END = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000001)) = 0x03078001
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchSmm.h
+PchSmmCore.c
+PchSmmHelpers.h
+PchSmmHelpers.c
+PchxSmmHelpers.h
+PchxSmmHelpers.c
+PchSmmUsb.c
+PchSmmGpi.c
+PchSmmPowerButton.c
+PchSmmSw.c
+PchSmmSx.c
+PchSmmPeriodicTimer.c
+IoTrap.c
+PchSmiDispatch.c
+PchSmmEspi.c
+
+
+[Protocols]
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gEfiSmmGpiDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSxDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSwDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmUsbDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPowerButtonDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmBase2ProtocolGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gEfiSmmReadyToLockProtocolGuid ## CONSUMES
+gEfiSmmIoTrapDispatch2ProtocolGuid ## PRODUCES
+gPchSmmIoTrapControlGuid ## PRODUCES
+gPchTcoSmiDispatchProtocolGuid ## PRODUCES
+gPchPcieSmiDispatchProtocolGuid ## PRODUCES
+gPchAcpiSmiDispatchProtocolGuid ## PRODUCES
+gPchGpioUnlockSmiDispatchProtocolGuid ## PRODUCES
+gPchSmiDispatchProtocolGuid ## PRODUCES
+gPchEspiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmmPeriodicTimerControlGuid ## PRODUCES
+gPchNvsAreaProtocolGuid ## CONSUMES
+
+
+[Guids]
+
+
+[Depex]
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND ## This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmCpuProtocolGuid AND
+gEfiSmmBase2ProtocolGuid AND ## This is for SmmServicesTableLib
+gPchNvsAreaProtocolGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
new file mode 100644
index 0000000000..7e4cce83f3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
@@ -0,0 +1,949 @@
+/** @file
+ Prototypes and defines for the PCH SMM Dispatcher.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef PCH_SMM_H
+#define PCH_SMM_H
+
+#include <Uefi.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/SmmUsbDispatch2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmGpiDispatch2.h>
+#include <Protocol/SmmPowerButtonDispatch2.h>
+#include <Protocol/SmmPeriodicTimerDispatch2.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PerformanceLib.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchEspiLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchAcpiSmiDispatch.h>
+#include <Protocol/PchGpioUnlockSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Protocol/PchEspiSmiDispatch.h>
+#include "IoTrap.h"
+
+#define EFI_BAD_POINTER 0xAFAFAFAFAFAFAFAFULL
+
+extern BOOLEAN mReadyToLock;
+
+///
+/// Define an enumeration for all the supported protocols
+///
+#define PCH_SMM_PROTOCOL_TYPE_MAX 6
+
+typedef enum {
+ UsbType,
+ SxType,
+ SwType,
+ GpiType,
+ PowerButtonType,
+ PeriodicTimerType,
+ PchSmiDispatchType,
+ PchSmmProtocolTypeMax
+} PCH_SMM_PROTOCOL_TYPE;
+
+///
+/// Define all the supported types of PCH SMI
+///
+typedef enum {
+ PchTcoSmiMchType,
+ PchTcoSmiTcoTimeoutType,
+ PchTcoSmiOsTcoType,
+ PchTcoSmiNmiType,
+ PchTcoSmiIntruderDetectType,
+ PchTcoSmiSpiBiosWpType,
+ PchTcoSmiLpcBiosWpType,
+ PchTcoSmiNewCenturyType,
+ PchPcieSmiRpHotplugType,
+ PchPcieSmiRpLinkActiveType,
+ PchPcieSmiRpLinkEqType,
+ PchAcpiSmiPmeType,
+ PchAcpiSmiPmeB0Type,
+ PchAcpiSmiRtcAlarmType,
+ PchAcpiSmiTmrOverflowType,
+ PchGpioUnlockSmiType,
+ PchEspiSmiEspiSlaveType,
+ PchSmiSerialIrqType,
+ PchSmiMcSmiType,
+ PchSmiSmBusType,
+ PchSmiSpiAsyncType,
+ PchIoTrapSmiType ///< internal SMI type
+} PCH_SMI_TYPES;
+
+///
+/// Generic funciton pointer to cover all Pch SMI function pointer types
+///
+typedef
+VOID
+(EFIAPI *PCH_SMI_CALLBACK_FUNCTIONS) (
+ IN EFI_HANDLE DispatchHandle,
+ ...
+ );
+
+
+///
+/// SPECIFYING A REGISTER
+/// We want a general way of referring to addresses. For this case, we'll only
+/// need addresses in the ACPI table (and the TCO entries within the ACPI table).
+/// However, it's interesting to consider what it would take to support other types
+/// of addresses. To address Will's concern, I think it prudent to accommodate it
+/// early on in the design.
+///
+/// Addresses we need to consider:
+///
+/// Type: Required:
+/// I/O Yes
+/// ACPI (special case of I/O) Only if we want to
+/// TCO (special case of I/O) Only if we want to
+/// GPIO (special case of MMIO) Only if we want to
+/// Memory (or Memory Mapped I/O) Only if we want to
+/// PCIE Yes, for BiosWp
+///
+typedef enum {
+ ///
+ /// IO_ADDR_TYPE, /// unimplemented
+ ///
+ ACPI_ADDR_TYPE,
+ TCO_ADDR_TYPE,
+ ///
+ /// MEMORY_ADDR_TYPE, /// unimplemented
+ ///
+ GPIO_ADDR_TYPE,
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCIE_ADDR_TYPE,
+ PCR_ADDR_TYPE,
+ NUM_ADDR_TYPES, ///< count of items in this enum
+ PCH_SMM_ADDR_TYPE_NULL = -1 ///< sentinel to indicate NULL or to signal end of arrays
+} ADDR_TYPE;
+
+//
+// Assumption: 32-bits -- enum's evaluate to integer
+// Assumption: This code will only run on IA-32. Justification: IA-64 doesn't have SMIs.
+// We don't have to worry about 64-bit addresses.
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case
+// this changes. This is a good idea because PCI_ADDR will change, for example, when
+// we add support for PciExpress.
+//
+typedef UINT16 IO_ADDR;
+typedef IO_ADDR ACPI_ADDR; ///< can omit
+typedef IO_ADDR TCO_ADDR; ///< can omit
+typedef UINTN MEM_ADDR;
+typedef MEM_ADDR *MEMORY_MAPPED_IO_ADDRESS;
+typedef MEM_ADDR *GPIO_ADDR;
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT32 Reg: 16;
+ UINT32 Fnc: 3;
+ UINT32 Dev: 5;
+ UINT32 Bus: 8;
+ } Fields;
+} PCIE_ADDR;
+
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT16 Offset;
+ UINT8 Pid;
+ UINT8 Base;
+ } Fields;
+} PCR_ADDR;
+
+typedef struct {
+ ADDR_TYPE Type;
+ union {
+ ///
+ /// used to initialize during declaration/definition
+ ///
+ UINT32 raw;
+
+ ///
+ /// used to access useful data
+ ///
+ IO_ADDR io;
+ ACPI_ADDR acpi;
+ TCO_ADDR tco;
+ GPIO_ADDR gpio;
+ MEM_ADDR mem;
+ MEMORY_MAPPED_IO_ADDRESS Mmio;
+ PCIE_ADDR pcie;
+ PCR_ADDR Pcr;
+
+ } Data;
+
+} PCH_SMM_ADDRESS;
+
+///
+/// SPECIFYING BITS WITHIN A REGISTER
+/// Here's a struct that helps us specify a source or enable bit.
+///
+typedef struct {
+ PCH_SMM_ADDRESS Reg;
+ UINT8 SizeInBytes; ///< of the register
+ UINT8 Bit;
+} PCH_SMM_BIT_DESC;
+
+//
+// Sometimes, we'll have bit descriptions that are unused. It'd be great to have a
+// way to easily identify them:
+//
+#define IS_BIT_DESC_NULL(BitDesc) ((BitDesc).Reg.Type == PCH_SMM_ADDR_TYPE_NULL) ///< "returns" true when BitDesc is NULL
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = PCH_SMM_ADDR_TYPE_NULL) ///< will "return" an integer w/ value of 0
+#define NULL_BIT_DESC_INITIALIZER \
+ { \
+ { \
+ PCH_SMM_ADDR_TYPE_NULL, \
+ { \
+ 0 \
+ } \
+ }, \
+ 0, 0 \
+ }
+//
+// I'd like a type to specify the callback's Sts & En bits because they'll
+// be commonly used together:
+//
+#define NUM_EN_BITS 2
+#define NUM_STS_BITS 1
+
+//
+// Flags
+//
+typedef UINT8 PCH_SMM_SOURCE_FLAGS;
+
+//
+// Flags required to describe the event source
+//
+#define PCH_SMM_NO_FLAGS 0
+#define PCH_SMM_SCI_EN_DEPENDENT 1
+
+typedef struct {
+ PCH_SMM_SOURCE_FLAGS Flags;
+ PCH_SMM_BIT_DESC En[NUM_EN_BITS]; ///< Describes the enable bit(s) for the SMI event
+ PCH_SMM_BIT_DESC Sts[NUM_STS_BITS]; ///< Describes the secondary status bit for the SMI event. Might be the same as TopLevelSmi
+ PCH_SMM_BIT_DESC PmcSmiSts; ///< Refereing to the top level status bit in PMC SMI_STS, i.e. R_PCH_SMI_STS
+} PCH_SMM_SOURCE_DESC;
+
+///
+/// Used to initialize null source descriptor
+///
+#define NULL_SOURCE_DESC_INITIALIZER \
+ { \
+ PCH_SMM_NO_FLAGS, \
+ { \
+ NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
+ }, \
+ { \
+ NULL_BIT_DESC_INITIALIZER \
+ }, \
+ NULL_BIT_DESC_INITIALIZER \
+ }
+
+///
+/// CHILD CONTEXTS
+/// To keep consistent w/ the architecture, we'll need to provide the context
+/// to the child when we call its callback function. After talking with Will,
+/// we agreed that we'll need functions to "dig" the context out of the hardware
+/// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
+/// contexts to prevent unnecessary dispatches. I'd like a general type for these
+/// "GetContext" functions, so I'll need a union of all the protocol contexts for
+/// our internal use:
+///
+typedef union {
+ //
+ // (in no particular order)
+ //
+ EFI_SMM_SX_REGISTER_CONTEXT Sx;
+ EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;
+ EFI_SMM_SW_REGISTER_CONTEXT Sw;
+ EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT PowerButton;
+ EFI_SMM_USB_REGISTER_CONTEXT Usb;
+ EFI_SMM_GPI_REGISTER_CONTEXT Gpi;
+} PCH_SMM_CONTEXT;
+
+///
+/// Misc data for PchDispatcher usage.
+/// For PeriodicTimer, since the ElapsedTime is removed from EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT of EDKII,
+/// and PchDispatcher needs it for every record. Thus move it here to support ElapsedTime.
+///
+typedef union {
+ UINTN ElapsedTime;
+} PCH_SMM_MISC_DATA;
+
+//
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
+//
+typedef struct _DATABASE_RECORD DATABASE_RECORD;
+
+///
+/// Assumption: the GET_CONTEXT function will be as small and simple as possible.
+/// Assumption: We don't need to pass in an enumeration for the protocol because each
+/// GET_CONTEXT function is written for only one protocol.
+/// We also need a function to compare contexts to see if the child should be dispatched
+/// In addition, we need a function to acquire CommBuffer and CommBufferSize for
+/// dispatch callback function of EDKII native support.
+///
+typedef
+VOID
+(EFIAPI *GET_CONTEXT) (
+ IN DATABASE_RECORD * Record,
+ OUT PCH_SMM_CONTEXT * Context
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *CMP_CONTEXT) (
+ IN PCH_SMM_CONTEXT * Context1,
+ IN PCH_SMM_CONTEXT * Context2
+ );
+
+typedef
+VOID
+(EFIAPI *GET_COMMBUFFER) (
+ IN DATABASE_RECORD * Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN * CommBufferSize
+ );
+
+///
+/// Finally, every protocol will require a "Get Context" and "Compare Context" call, so
+/// we may as well wrap that up in a table, too.
+///
+typedef struct {
+ GET_CONTEXT GetContext;
+ CMP_CONTEXT CmpContext;
+ GET_COMMBUFFER GetCommBuffer;
+} CONTEXT_FUNCTIONS;
+
+extern CONTEXT_FUNCTIONS ContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX];
+
+///
+/// MAPPING CONTEXT TO BIT DESCRIPTIONS
+/// I'd like to have a general approach to mapping contexts to bit descriptions.
+/// Sometimes, we'll find that we can use table lookups or constant assignments;
+/// other times, we'll find that we'll need to use a function to perform the mapping.
+/// If we define a macro to mask that process, we'll never have to change the code.
+/// I don't know if this is desirable or not -- if it isn't, then we can get rid
+/// of the macros and just use function calls or variable assignments. Doesn't matter
+/// to me.
+/// Mapping complex contexts requires a function
+///
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[out] SrcDesc The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+//
+// Mapping simple contexts can be done by assignment or lookup table
+//
+extern CONST PCH_SMM_SOURCE_DESC SW_SOURCE_DESC;
+extern CONST PCH_SMM_SOURCE_DESC SX_SOURCE_DESC;
+extern CONST PCH_SMM_SOURCE_DESC POWER_BUTTON_SOURCE_DESC;
+
+//
+// With the changes we've made to the protocols, we can now use table
+// lookups for the following protocols:
+//
+extern CONST PCH_SMM_SOURCE_DESC PCH_GPI_SOURCE_DESC_TEMPLATE;
+
+///
+/// For PCHx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
+///
+#define MAXIMUM_SWI_VALUE 0xFF
+///
+/// Open: Need to make sure this kind of type cast will actually work.
+/// May need an intermediate form w/ two VOID* arguments. I'll figure
+/// that out when I start compiling.
+///
+typedef
+VOID
+(EFIAPI *PCH_SMM_CLEAR_SOURCE) (
+ PCH_SMM_SOURCE_DESC * SrcDesc
+ );
+
+///
+/// "DATABASE" RECORD
+/// Linked list data structures
+///
+#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')
+
+struct _DATABASE_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ BOOLEAN Processed;
+ ///
+ /// Status and Enable bit description
+ ///
+ PCH_SMM_SOURCE_DESC SrcDesc;
+
+ ///
+ /// Callback function
+ ///
+ EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
+ PCH_SMM_CONTEXT ChildContext;
+
+ ///
+ /// Special handling hooks -- init them to NULL if unused/unneeded
+ ///
+ PCH_SMM_CLEAR_SOURCE ClearSource; ///< needed for SWSMI timer
+
+ ///
+ /// Functions required to make callback code general
+ ///
+ CONTEXT_FUNCTIONS ContextFunctions;
+
+ ///
+ /// The protocol that this record dispatches
+ ///
+ PCH_SMM_PROTOCOL_TYPE ProtocolType;
+
+ ///
+ /// Misc data for private usage
+ ///
+ PCH_SMM_MISC_DATA MiscData;
+
+ ///
+ /// PCH SMI callback function
+ ///
+ PCH_SMI_CALLBACK_FUNCTIONS PchSmiCallback;
+ ///
+ /// Indicate the PCH SMI types.
+ ///
+ PCH_SMI_TYPES PchSmiType;
+};
+
+#define DATABASE_RECORD_FROM_LINK(_record) CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
+#define DATABASE_RECORD_FROM_CHILDCONTEXT(_record) CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)
+
+///
+/// HOOKING INTO THE ARCHITECTURE
+///
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_REGISTER) (
+ IN VOID **This,
+ IN VOID *DispatchFunction,
+ IN VOID *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_UNREGISTER) (
+ IN VOID **This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+///
+/// Define a memory "stamp" equivalent in size and function to most of the protocols
+///
+typedef struct {
+ PCH_SMM_GENERIC_REGISTER Register;
+ PCH_SMM_GENERIC_UNREGISTER Unregister;
+ UINTN Extra1;
+ UINTN Extra2; ///< may not need this one
+} PCH_SMM_GENERIC_PROTOCOL;
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+PchSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ );
+
+typedef union {
+ PCH_SMM_GENERIC_PROTOCOL Generic;
+ EFI_SMM_USB_DISPATCH2_PROTOCOL Usb;
+ EFI_SMM_SX_DISPATCH2_PROTOCOL Sx;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL Sw;
+ EFI_SMM_GPI_DISPATCH2_PROTOCOL Gpi;
+ EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL PowerButton;
+ EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL PeriodicTimer;
+} PCH_SMM_PROTOCOL;
+
+///
+/// Define a structure to help us identify the generic protocol
+///
+#define PROTOCOL_SIGNATURE SIGNATURE_32 ('P', 'R', 'O', 'T')
+
+typedef struct {
+ UINTN Signature;
+
+ PCH_SMM_PROTOCOL_TYPE Type;
+ EFI_GUID *Guid;
+ PCH_SMM_PROTOCOL Protocols;
+} PCH_SMM_QUALIFIED_PROTOCOL;
+
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
+ CR ( \
+ _generic, \
+ PCH_SMM_QUALIFIED_PROTOCOL, \
+ Protocols, \
+ PROTOCOL_SIGNATURE \
+ )
+
+///
+/// Create private data for the protocols that we'll publish
+///
+typedef struct {
+ LIST_ENTRY CallbackDataBase;
+ EFI_HANDLE SmiHandle;
+ EFI_HANDLE InstallMultProtHandle;
+ PCH_SMM_QUALIFIED_PROTOCOL Protocols[PCH_SMM_PROTOCOL_TYPE_MAX];
+} PRIVATE_DATA;
+
+extern PRIVATE_DATA mPrivateData;
+extern UINT16 mAcpiBaseAddr;
+extern UINT16 mTcoBaseAddr;
+/**
+ Get the Software Smi value
+
+ @param[in] Record No use
+ @param[out] Context The context that includes Software Smi value to be filled
+
+**/
+VOID
+EFIAPI
+SwGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether software SMI value of two contexts match
+
+ @param[in] Context1 Context 1 that includes software SMI value 1
+ @param[in] Context2 Context 2 that includes software SMI value 2
+
+ @retval FALSE Software SMI value match
+ @retval TRUE Software SMI value don't match
+**/
+BOOLEAN
+EFIAPI
+SwCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Gather the CommBuffer information of SmmSwDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+SwGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ );
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Init required protocol for Pch Sw Dispatch protocol.
+
+
+**/
+VOID
+PchSwDispatchInit (
+ VOID
+ );
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ );
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ );
+
+/**
+ Install PCH SMM periodic timer control protocol
+
+ @param[in] Handle handle for this driver
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ );
+
+/**
+ Check and clear NEWCENTURY_STS.
+ It will clear the SMI status once it happens.
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+**/
+VOID
+EFIAPI
+PchTcoClearNewCenturySts (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Install protocols of PCH specifics SMI types, including
+ PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+ @retval the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+ VOID
+ );
+
+/**
+ The function to dispatch all callback function of PCH SMI types.
+
+ @retval EFI_SUCCESS Function successfully completed
+ @retval EFI_UNSUPPORTED no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+ IN DATABASE_RECORD *Record
+ );
+
+/**
+ The register function used to register SMI handler of IoTrap event.
+ This is internal function and only used by Iotrap module.
+
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] IoTrapIndex Index number of IOTRAP register
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN IoTrapIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register an eSPI SMI handler based on the type
+
+ @param[in] DispatchFunction Callback in an event of eSPI SMI
+ @param[in] PchSmiTypes The eSPI type published by PchSmiDispatch
+ @param[out] DispatchHandle The callback handle
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS Registration is successful.
+**/
+EFI_STATUS
+PchInternalEspiSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiTypes,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister an eSPI SMI handler
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalEspiSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ The internal function used to create and insert a database record
+ for SMI record of Pch Smi types.
+
+ @param[in] SrcDesc The pointer to the SMI source description
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] PchSmiType Specific SMI type of PCH SMI
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc,
+ IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+extern PCH_SMM_SOURCE_DESC mSrcDescSerialIrq;
+
+/**
+ Clear the TCO SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Initialize Source descriptor structure
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+NullInitSourceDesc (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
new file mode 100644
index 0000000000..977a7ec57c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
@@ -0,0 +1,952 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include "PchSmmEspi.h"
+
+//
+// MODULE / GLOBAL DATA
+//
+// Module variables used by the both the main dispatcher and the source dispatchers
+// Declared in PchSmm.h
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mAcpiBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mTcoBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mReadyToLock;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PRIVATE_DATA mPrivateData = {
+ {
+ NULL,
+ NULL
+ }, ///< CallbackDataBase linked list head
+ NULL, ///< EFI handle returned when calling InstallMultipleProtocolInterfaces
+ NULL, //
+ { ///< protocol arrays
+ ///
+ /// elements within the array
+ ///
+ {
+ PROTOCOL_SIGNATURE,
+ UsbType,
+ &gEfiSmmUsbDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SxType,
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SwType,
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) MAXIMUM_SWI_VALUE
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ GpiType,
+ &gEfiSmmGpiDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) V_PCH_GPIO_NUM_SUPPORTED_GPIS
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PowerButtonType,
+ &gEfiSmmPowerButtonDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PeriodicTimerType,
+ &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) PchSmmPeriodicTimerDispatchGetNextShorterInterval
+ }}
+ },
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONTEXT_FUNCTIONS mContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX] = {
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ SxGetContext,
+ SxCmpContext,
+ NULL
+ },
+ {
+ SwGetContext,
+ SwCmpContext,
+ SwGetCommBuffer
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ PowerButtonGetContext,
+ PowerButtonCmpContext,
+ NULL
+ },
+ {
+ PeriodicTimerGetContext,
+ PeriodicTimerCmpContext,
+ PeriodicTimerGetCommBuffer
+ },
+};
+
+//
+// PROTOTYPES
+//
+// Functions use only in this file
+//
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN CONST VOID *PchSmmCore, OPTIONAL
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ );
+
+//
+// FUNCTIONS
+//
+/**
+ SMM ready to lock notification event handler.
+
+ @param Protocol Points to the protocol's unique identifier
+ @param Interface Points to the interface instance
+ @param Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmReadyToLockCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmReadyToLockCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ mReadyToLock = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ <b>PchSmiDispatcher SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchSmiDispatcher module is an SMM driver which provides SMI handler registration
+ services for PCH generated SMIs.
+
+ - <b>Details</b>\n
+ This module provides SMI handler registration servicies for PCH SMIs.
+ NOTE: All the register/unregister functions will be locked after SMM ready to boot signal event.
+ Please make sure no handler is installed after that.
+
+ - @pre
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification
+ - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ - Documented in the UEFI 2.0 Specification and above
+ - 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_CPU_PROTOCOL
+
+ - @result
+ The PchSmiDispatcher driver produces:
+ - EFI_SMM_USB_DISPATCH2_PROTOCOL
+ - EFI_SMM_SX_DISPATCH2_PROTOCOL
+ - EFI_SMM_SW_DISPATCH2_PROTOCOL
+ - EFI_SMM_GPI_DISPATCH2_PROTOCOL
+ - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+ - EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL
+ - EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL
+ - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_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_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL @endlink
+
+ @param[in] ImageHandle Pointer to the loaded image protocol for this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS PchSmmDispatcher Initialization completed.
+**/
+EFI_STATUS
+EFIAPI
+InitializePchSmmDispatcher (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINTN LpcBaseAddress;
+ EFI_STATUS Status;
+ VOID *SmmReadyToLockRegistration;
+
+ ///
+ /// Access ACPI Base Addresses Register
+ ///
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ PchAcpiBaseGet (&mAcpiBaseAddr);
+ ASSERT (mAcpiBaseAddr != 0);
+
+ ///
+ /// Access TCO Base Addresses Register
+ ///
+ PchTcoBaseGet (&mTcoBaseAddr);
+ ASSERT (mTcoBaseAddr != 0);
+
+
+ PchSwDispatchInit ();
+
+ ///
+ /// Register a callback function to handle subsequent SMIs. This callback
+ /// will be called by SmmCoreDispatcher.
+ ///
+ Status = gSmst->SmiHandlerRegister (PchSmmCoreDispatcher, NULL, &mPrivateData.SmiHandle);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Initialize Callback DataBase
+ ///
+ InitializeListHead (&mPrivateData.CallbackDataBase);
+
+ ///
+ /// Enable SMIs on the PCH now that we have a callback
+ ///
+ PchSmmInitHardware ();
+
+ //
+ // Install and initialize all the needed protocols
+ //
+ PchSmmPublishDispatchProtocols ();
+ InstallPchSmiDispatchProtocols ();
+ InstallIoTrap (ImageHandle);
+ InstallEspiSmi (ImageHandle);
+ InstallPchSmmPeriodicTimerControlProtocol (mPrivateData.InstallMultProtHandle);
+
+ //
+ // Register EFI_SMM_READY_TO_LOCK_PROTOCOL_GUID notify function.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ SmmReadyToLockCallback,
+ &SmmReadyToLockRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check the Fed SwSmiInputValue to see if there is a duplicated one in the database
+
+ @param[in] FedSwSmiInputValue Fed SwSmiInputValue
+
+ @retval EFI_SUCCESS There is no duplicated SwSmiInputValue
+ @retval EFI_INVALID_PARAMETER There is a duplicated SwSmiInputValue
+**/
+EFI_STATUS
+SmiInputValueDuplicateCheck (
+ UINTN FedSwSmiInputValue
+ )
+{
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ if (RecordInDb->ProtocolType == SwType) {
+ if (RecordInDb->ChildContext.Sw.SwSmiInputValue == FedSwSmiInputValue) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+PchSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+ PCH_SMM_QUALIFIED_PROTOCOL *Qualified;
+ PCH_SMM_SOURCE_DESC NullSourceDesc;
+ UINTN Index;
+ GPIO_PAD GpioPad;
+ UINT8 GpiSmiBitOffset;
+ UINT32 GpiSmiEnRegAddress;
+ UINT32 GpiSmiStsRegAddress;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ //
+ // Initialize NullSourceDesc
+ //
+ NullInitSourceDesc (&NullSourceDesc);
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Index = 0;
+ ///
+ /// Create database record and add to database
+ ///
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ZeroMem (Record, sizeof (DATABASE_RECORD));
+
+ ///
+ /// Gather information about the registration request
+ ///
+ Record->Callback = DispatchFunction;
+
+ Qualified = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+
+ Record->ProtocolType = Qualified->Type;
+
+ Record->ContextFunctions = mContextFunctions[Qualified->Type];
+ ///
+ /// Perform linked list housekeeping
+ ///
+ Record->Signature = DATABASE_RECORD_SIGNATURE;
+
+ switch (Qualified->Type) {
+ ///
+ /// By the end of this switch statement, we'll know the
+ /// source description the child is registering for
+ ///
+ case UsbType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_USB_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Type
+ ///
+ if ((Record->ChildContext.Usb.Type < UsbLegacy) || (Record->ChildContext.Usb.Type > UsbWake)) {
+ goto Error;
+ }
+
+ MapUsbToSrcDesc (DispatchContext, &(Record->SrcDesc));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case SxType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_SX_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Type and Phase
+ ///
+ if ((Record->ChildContext.Sx.Type < SxS0) ||
+ (Record->ChildContext.Sx.Type >= EfiMaximumSleepType) ||
+ (Record->ChildContext.Sx.Phase < SxEntry) ||
+ (Record->ChildContext.Sx.Phase >= EfiMaximumPhase)
+ ) {
+ goto Error;
+ }
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (&SX_SOURCE_DESC), sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case SwType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_SW_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Value
+ ///
+ if (Record->ChildContext.Sw.SwSmiInputValue == (UINTN) -1) {
+ for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {
+ if (!EFI_ERROR (SmiInputValueDuplicateCheck (Index))) {
+ Record->ChildContext.Sw.SwSmiInputValue = Index;
+ break;
+ }
+ }
+ if (Record->ChildContext.Sw.SwSmiInputValue == (UINTN) -1) {
+ goto Error;
+ }
+ }
+ if (Record->ChildContext.Sw.SwSmiInputValue > MAXIMUM_SWI_VALUE) {
+ goto Error;
+ }
+
+ if (EFI_ERROR (SmiInputValueDuplicateCheck (Record->ChildContext.Sw.SwSmiInputValue))) {
+ goto Error;
+ }
+ CopyMem (DispatchContext, &Record->ChildContext, sizeof (EFI_SMM_SW_REGISTER_CONTEXT));
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (&SW_SOURCE_DESC), sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case GpiType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_GPI_REGISTER_CONTEXT));
+
+ Index = Record->ChildContext.Gpi.GpiNum;
+
+ Status = GpioGetPadAndSmiRegs (
+ (UINT32) Index,
+ &GpioPad,
+ &GpiSmiBitOffset,
+ &GpiSmiEnRegAddress,
+ &GpiSmiStsRegAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ CopyMem (
+ (VOID *) &(Record->SrcDesc),
+ (VOID *) &(PCH_GPI_SOURCE_DESC_TEMPLATE),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+ Record->SrcDesc.En[0].Reg.Data.raw = GpiSmiEnRegAddress; // GPI SMI Enable register
+ Record->SrcDesc.En[0].Bit = GpiSmiBitOffset; // Bit position for selected pad
+ Record->SrcDesc.Sts[0].Reg.Data.raw = GpiSmiStsRegAddress; // GPI SMI Status register
+ Record->SrcDesc.Sts[0].Bit = GpiSmiBitOffset; // Bit position for selected pad
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ ///
+ /// Add GPI_SMI_EN programming into S3 boot script
+ ///
+ Data32Or = (1u << GpiSmiBitOffset);
+ Data32And = 0xFFFFFFFF;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, GpiSmiEnRegAddress, &Data32Or, &Data32And);
+
+ break;
+
+ case PowerButtonType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Phase
+ ///
+ if ((Record->ChildContext.PowerButton.Phase < EfiPowerButtonEntry) ||
+ (Record->ChildContext.PowerButton.Phase > EfiPowerButtonExit)
+ ) {
+ goto Error;
+ }
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) &POWER_BUTTON_SOURCE_DESC, sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case PeriodicTimerType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of timer value
+ ///
+ if (DispatchContext->PeriodicTimer.SmiTickInterval <= 0) {
+ goto Error;
+ }
+
+ MapPeriodicTimerToSrcDesc (DispatchContext, &(Record->SrcDesc));
+ Record->ClearSource = PchSmmPeriodicTimerClearSource;
+ break;
+
+ default:
+ goto Error;
+ break;
+ }
+
+ if (CompareSources (&Record->SrcDesc, &NullSourceDesc)) {
+ goto Error;
+ }
+
+ ///
+ /// After ensuring the source of event is not null, we will insert the record into the database
+ ///
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+
+ if (Record->ClearSource == NULL) {
+ ///
+ /// Clear the SMI associated w/ the source using the default function
+ ///
+ PchSmmClearSource (&Record->SrcDesc);
+ } else {
+ ///
+ /// This source requires special handling to clear
+ ///
+ Record->ClearSource (&Record->SrcDesc);
+ }
+
+ PchSmmEnableSource (&Record->SrcDesc);
+
+ ///
+ /// Child's handle will be the address linked list link in the record
+ ///
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+
+Error:
+ Status = gSmst->SmmFreePool (Record);
+ ///
+ /// DEBUG((DEBUG_ERROR,"Free pool status %d\n", Status ));
+ ///
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN NeedClearEnable;
+ UINTN DescIndex;
+ DATABASE_RECORD *RecordToDelete;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ //
+ // Take the entry out of the linked list
+ //
+ if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+
+ //
+ // Loop through all the souces in record linked list to see if any source enable is equal.
+ // If any source enable is equal, we do not want to disable it.
+ //
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+ if (IS_BIT_DESC_NULL (RecordToDelete->SrcDesc.En[DescIndex])) {
+ continue;
+ }
+ NeedClearEnable = TRUE;
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (IsBitEqualToAnySourceEn (&RecordToDelete->SrcDesc.En[DescIndex], &RecordInDb->SrcDesc)) {
+ NeedClearEnable = FALSE;
+ break;
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ if (NeedClearEnable == FALSE) {
+ continue;
+ }
+ WriteBitDesc (&RecordToDelete->SrcDesc.En[DescIndex], 0, FALSE);
+ }
+
+ Status = gSmst->SmmFreePool (RecordToDelete);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function clears the pending SMI status before set EOS.
+ NOTE: This only clears the pending SMI with known reason.
+ Please do not clear unknown pending SMI status since that will hide potential issues.
+
+ @param[in] SmiStsValue SMI status
+**/
+static
+VOID
+ClearPendingSmiStatus (
+ UINT32 SmiStsValue
+ )
+{
+ //
+ // Clear NewCentury status if it's not handled.
+ //
+ if (SmiStsValue & B_PCH_SMI_STS_TCO) {
+ PchTcoClearNewCenturySts (NULL);
+ }
+ // Clear PWRBTNOR_STS if it's not handled.
+ //
+ if (IoRead16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS) & B_PCH_ACPI_PM1_STS_PRBTNOR) {
+ IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PRBTNOR);
+ }
+ //
+ // Clear SWSMI if this is triggered by SmmControl.
+ //
+ if (SmiStsValue & B_PCH_SMI_STS_APM) {
+ IoWrite32 (mAcpiBaseAddr + R_PCH_SMI_STS, B_PCH_SMI_STS_APM);
+ }
+}
+
+/**
+ The callback function to handle subsequent SMIs. This callback will be called by SmmCoreDispatcher.
+
+ @param[in] SmmImageHandle Not used
+ @param[in] PchSmmCore Not used
+ @param[in, out] CommunicationBuffer Not used
+ @param[in, out] SourceSize Not used
+
+ @retval EFI_SUCCESS Function successfully completed
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN CONST VOID *PchSmmCore,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+ ///
+ /// Used to prevent infinite loops
+ ///
+ UINTN EscapeCount;
+
+ BOOLEAN ContextsMatch;
+ BOOLEAN EosSet;
+ BOOLEAN SxChildWasDispatched;
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ DATABASE_RECORD *RecordToExhaust;
+ LIST_ENTRY *LinkToExhaust;
+
+ PCH_SMM_CONTEXT Context;
+ VOID *CommBuffer;
+ UINTN CommBufferSize;
+
+ EFI_STATUS Status;
+ BOOLEAN SciEn;
+ UINT32 SmiEnValue;
+ UINT32 SmiStsValue;
+ UINT8 Port74Save;
+ UINT8 Port76Save;
+
+ PCH_SMM_SOURCE_DESC ActiveSource;
+
+ //
+ // Initialize ActiveSource
+ //
+ NullInitSourceDesc (&ActiveSource);
+
+ EscapeCount = 3;
+ ContextsMatch = FALSE;
+ EosSet = FALSE;
+ SxChildWasDispatched = FALSE;
+ Status = EFI_SUCCESS;
+
+ //
+ // Save IO index registers
+ // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+ // then save/restore 74h/76h instead.
+ // @note: CF8 is not saved. Prefer method is to use MMIO instead of CF8
+ //
+ Port76Save = IoRead8 (R_PCH_RTC_EXT_INDEX_ALT);
+ Port74Save = IoRead8 (R_PCH_RTC_INDEX_ALT);
+
+ if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {
+ ///
+ /// We have children registered w/ us -- continue
+ ///
+ while ((!EosSet) && (EscapeCount > 0)) {
+ EscapeCount--;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+
+ ///
+ /// Cache SciEn, SmiEnValue and SmiStsValue to determine if source is active
+ ///
+ SciEn = PchSmmGetSciEn ();
+ SmiEnValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+ SmiStsValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS));
+
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ ///
+ /// look for the first active source
+ ///
+ if (!SourceIsActive (&RecordInDb->SrcDesc, SciEn, SmiEnValue, SmiStsValue)) {
+ ///
+ /// Didn't find the source yet, keep looking
+ ///
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+
+ ///
+ /// if it's the last one, try to clear EOS
+ ///
+ if (IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ //
+ // Clear pending SMI status before EOS
+ //
+ ClearPendingSmiStatus (SmiStsValue);
+ EosSet = PchSmmSetAndCheckEos ();
+ }
+ } else {
+ ///
+ /// We found a source. If this is a sleep type, we have to go to
+ /// appropriate sleep state anyway.No matter there is sleep child or not
+ ///
+ if (RecordInDb->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ ///
+ /// "cache" the source description and don't query I/O anymore
+ ///
+ CopyMem ((VOID *) &ActiveSource, (VOID *) &(RecordInDb->SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+ LinkToExhaust = LinkInDb;
+
+ ///
+ /// exhaust the rest of the queue looking for the same source
+ ///
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {
+ RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);
+ ///
+ /// RecordToExhaust->Link might be removed (unregistered) by Callback function, and then the
+ /// system will hang in ASSERT() while calling GetNextNode().
+ /// To prevent the issue, we need to get next record in DB here (before Callback function).
+ ///
+ LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);
+
+ if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {
+ ///
+ /// These source descriptions are equal, so this callback should be
+ /// dispatched.
+ ///
+ if (RecordToExhaust->ContextFunctions.GetContext != NULL) {
+ ///
+ /// This child requires that we get a calling context from
+ /// hardware and compare that context to the one supplied
+ /// by the child.
+ ///
+ ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);
+
+ ///
+ /// Make sure contexts match before dispatching event to child
+ ///
+ RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);
+ ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);
+
+ } else {
+ ///
+ /// This child doesn't require any more calling context beyond what
+ /// it supplied in registration. Simply pass back what it gave us.
+ ///
+ Context = RecordToExhaust->ChildContext;
+ ContextsMatch = TRUE;
+ }
+
+ if (ContextsMatch) {
+ if (RecordToExhaust->ProtocolType == PchSmiDispatchType) {
+ //
+ // For PCH SMI dispatch protocols
+ //
+ PchSmiTypeCallbackDispatcher (RecordToExhaust);
+ } else {
+ //
+ // For EFI standard SMI dispatch protocols
+ //
+ if (RecordToExhaust->Callback != NULL) {
+ if (RecordToExhaust->ContextFunctions.GetCommBuffer != NULL) {
+ ///
+ /// This callback function needs CommBuffer and CommBufferSize.
+ /// Get those from child and then pass to callback function.
+ ///
+ RecordToExhaust->ContextFunctions.GetCommBuffer (RecordToExhaust, &CommBuffer, &CommBufferSize);
+ } else {
+ ///
+ /// Child doesn't support the CommBuffer and CommBufferSize.
+ /// Just pass NULL value to callback function.
+ ///
+ CommBuffer = NULL;
+ CommBufferSize = 0;
+ }
+
+ PERF_START_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+ RecordToExhaust->Callback ((EFI_HANDLE) & RecordToExhaust->Link, &Context, CommBuffer, &CommBufferSize);
+ PERF_END_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+ if (RecordToExhaust->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+ }
+ }
+
+ if (RecordInDb->ClearSource == NULL) {
+ ///
+ /// Clear the SMI associated w/ the source using the default function
+ ///
+ PchSmmClearSource (&ActiveSource);
+ } else {
+ ///
+ /// This source requires special handling to clear
+ ///
+ RecordInDb->ClearSource (&ActiveSource);
+ }
+ //
+ // Clear pending SMI status before EOS
+ //
+ ClearPendingSmiStatus (SmiStsValue);
+ ///
+ /// Also, try to clear EOS
+ ///
+ EosSet = PchSmmSetAndCheckEos ();
+ ///
+ /// Queue is empty, reset the search
+ ///
+ break;
+ }
+ }
+ }
+ }
+ ///
+ /// If you arrive here, there are two possible reasons:
+ /// (1) you've got problems with clearing the SMI status bits in the
+ /// ACPI table. If you don't properly clear the SMI bits, then you won't be able to set the
+ /// EOS bit. If this happens too many times, the loop exits.
+ /// (2) there was a SMM communicate for callback messages that was received prior
+ /// to this driver.
+ /// If there is an asynchronous SMI that occurs while processing the Callback, let
+ /// all of the drivers (including this one) have an opportunity to scan for the SMI
+ /// and handle it.
+ /// If not, we don't want to exit and have the foreground app. clear EOS without letting
+ /// these other sources get serviced.
+ ///
+ /// This assert is not valid with CSM legacy solution because it generates software SMI
+ /// to test for legacy USB support presence.
+ /// This may not be illegal, so we cannot assert at this time.
+ ///
+ /// ASSERT (EscapeCount > 0);
+ ///
+ if (SxChildWasDispatched) {
+ ///
+ /// A child of the SmmSxDispatch protocol was dispatched during this call;
+ /// put the system to sleep.
+ ///
+ PchSmmSxGoToSleep ();
+ }
+ //
+ // Restore IO index registers
+ // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+ // then save/restore 74h/76h instead.
+ //
+ IoWrite8 (R_PCH_RTC_EXT_INDEX_ALT, Port76Save);
+ IoWrite8 (R_PCH_RTC_INDEX_ALT, Port74Save);
+
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c
new file mode 100644
index 0000000000..8484be18ea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c
@@ -0,0 +1,1385 @@
+/** @file
+ eSPI SMI implementation
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PchSmmEspi.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED ESPI_SMI_INSTANCE mEspiSmiInstance = {
+ //
+ // Signature
+ //
+ ESPI_SMI_INSTANCE_SIGNATURE,
+ //
+ // Handle
+ //
+ NULL,
+ //
+ // PchEspiSmiDispatchProtocol
+ //
+ {
+ PCH_ESPI_SMI_DISPATCH_REVISION,
+ EspiSmiUnRegister,
+ BiosWrProtectRegister,
+ BiosWrReportRegister,
+ PcNonFatalErrRegister,
+ PcFatalErrRegister,
+ VwNonFatalErrRegister,
+ VwFatalErrRegister,
+ FlashNonFatalErrRegister,
+ FlashFatalErrRegister,
+ LnkType1ErrRegister,
+ EspiSlaveSmiRegister
+ },
+ //
+ // PchSmiEspiHandle[EspiTopLevelTypeMax]
+ //
+ {
+ NULL, NULL, NULL
+ },
+ //
+ // CallbackDataBase[EspiSmiTypeMax]
+ //
+ {
+ {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL},
+ {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}
+ },
+ //
+ // EspiSmiEventCounter[EspiSmiTypeMax]
+ //
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ //
+ // Barrier[EspiTopLevelTypeMax]
+ //
+ {
+ {
+ BiosWrProtect,
+ BiosWrProtect
+ },
+ {
+ BiosWrReport,
+ LnkType1Err
+ },
+ {
+ EspiSlaveSmi,
+ EspiSlaveSmi
+ }
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST ESPI_DESCRIPTOR mEspiDescriptor[EspiSmiTypeMax] = {
+ //
+ // BiosWrProtect
+ //
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ //
+ // SourceIsActiveAndMask and SourceIsActiveValue
+ //
+ B_PCH_ESPI_PCBC_BWPDS | B_PCH_ESPI_PCBC_LE,
+ B_PCH_ESPI_PCBC_BWPDS | B_PCH_ESPI_PCBC_LE,
+ //
+ // ClearStatusAndMask and ClearStatusOrMask
+ //
+ (UINT32) ~B_PCH_ESPI_PCBC_BWRS,
+ B_PCH_ESPI_PCBC_BWPDS
+ },
+ //
+ // BiosWrReport
+ //
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWRE,
+ B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWRE,
+ (UINT32) ~B_PCH_ESPI_PCBC_BWPDS,
+ B_PCH_ESPI_PCBC_BWRS
+ },
+ //
+ // PcNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_PCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ (B_PCH_PCR_ESPI_XERR_XNFES | (V_PCH_PCR_ESPI_XERR_XNFEE_SMI << N_PCH_PCR_ESPI_XERR_XNFEE)),
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFES
+ },
+ //
+ // PcFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_PCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ (B_PCH_PCR_ESPI_XERR_XFES | (V_PCH_PCR_ESPI_XERR_XFEE_SMI << N_PCH_PCR_ESPI_XERR_XFEE)),
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES),
+ B_PCH_PCR_ESPI_XERR_XFES
+ },
+ //
+ // VwNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_VWERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ (B_PCH_PCR_ESPI_XERR_XNFES | (V_PCH_PCR_ESPI_XERR_XNFEE_SMI << N_PCH_PCR_ESPI_XERR_XNFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XFES,
+ B_PCH_PCR_ESPI_XERR_XNFES
+ },
+ //
+ // VwFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_VWERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ (B_PCH_PCR_ESPI_XERR_XFES | (V_PCH_PCR_ESPI_XERR_XFEE_SMI << N_PCH_PCR_ESPI_XERR_XFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XNFES,
+ B_PCH_PCR_ESPI_XERR_XFES
+ },
+ //
+ // FlashNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_FCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ (B_PCH_PCR_ESPI_XERR_XNFES | (V_PCH_PCR_ESPI_XERR_XNFEE_SMI << N_PCH_PCR_ESPI_XERR_XNFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XFES,
+ B_PCH_PCR_ESPI_XERR_XNFES
+ },
+ //
+ // FlashFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_FCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ (B_PCH_PCR_ESPI_XERR_XFES | (V_PCH_PCR_ESPI_XERR_XFEE_SMI << N_PCH_PCR_ESPI_XERR_XFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XNFES,
+ B_PCH_PCR_ESPI_XERR_XFES
+ },
+ //
+ // LnkType1Err
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_LNKERR_SLV0) }
+ },
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S | B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E,
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S | (V_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E_SMI << N_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E),
+ (UINT32) ~B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR,
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S
+ },
+};
+
+/**
+ Enable eSPI SMI source
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiEnableSource (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+ UINTN PciBaseAddress;
+
+ switch (EspiSmiType) {
+ case BiosWrProtect:
+ PciBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ MmioAndThenOr32 (
+ PciBaseAddress + R_PCH_ESPI_PCBC,
+ (UINT32) ~(B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWPDS),
+ B_PCH_ESPI_PCBC_LE
+ );
+ break;
+ case BiosWrReport:
+ PciBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ MmioAndThenOr32 (
+ PciBaseAddress + R_PCH_ESPI_PCBC,
+ (UINT32) ~(B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWPDS),
+ B_PCH_ESPI_PCBC_BWRE
+ );
+ break;
+ case PcNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case PcFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case LnkType1Err:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_LNKERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR | B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S),
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E);
+ ASSERT_EFI_ERROR (Status);
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported EspiSmiType \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+
+/**
+ Disable eSPI SMI source
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiDisableSource (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+
+ switch (EspiSmiType) {
+ case BiosWrProtect:
+ case BiosWrReport:
+ DEBUG ((DEBUG_ERROR, "Bit is write lock, thus BWRE/BWPDS source cannot be disabled \n"));
+ ASSERT (FALSE);
+ break;
+ case PcNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case PcFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case LnkType1Err:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_LNKERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR | B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported EspiSmiType \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Clear a status for the SMI event
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiClearStatus (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINT32 PciBaseAddress;
+ CONST ESPI_DESCRIPTOR *Desc;
+
+ Desc = &mEspiDescriptor[EspiSmiType];
+
+ switch (Desc->Address.Type) {
+ case PCIE_ADDR_TYPE:
+ PciBus = Desc->Address.Data.pcie.Fields.Bus;
+ PciDev = Desc->Address.Data.pcie.Fields.Dev;
+ PciFun = Desc->Address.Data.pcie.Fields.Fnc;
+ PciReg = Desc->Address.Data.pcie.Fields.Reg;
+ PciBaseAddress = (UINT32) MmPciBase (PciBus, PciDev, PciFun);
+ MmioAndThenOr32 (PciBaseAddress + PciReg, Desc->ClearStatusAndMask, Desc->ClearStatusOrMask);
+ break;
+ case PCR_ADDR_TYPE:
+ Status = PchPcrAndThenOr32 (
+ Desc->Address.Data.Pcr.Fields.Pid,
+ Desc->Address.Data.Pcr.Fields.Offset,
+ Desc->ClearStatusAndMask,
+ Desc->ClearStatusOrMask
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Address type for eSPI SMI is invalid \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Checks if a source is active by looking at the enable and status bits
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+BOOLEAN
+EspiSmiSourceIsActive (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Active;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINT32 PciBaseAddress;
+ UINT32 Data32;
+ CONST ESPI_DESCRIPTOR *Desc;
+
+ Desc = &mEspiDescriptor[EspiSmiType];
+
+ Active = FALSE;
+ switch (Desc->Address.Type) {
+ case PCIE_ADDR_TYPE:
+ PciBus = Desc->Address.Data.pcie.Fields.Bus;
+ PciDev = Desc->Address.Data.pcie.Fields.Dev;
+ PciFun = Desc->Address.Data.pcie.Fields.Fnc;
+ PciReg = Desc->Address.Data.pcie.Fields.Reg;
+ PciBaseAddress = (UINT32) MmPciBase (PciBus, PciDev, PciFun);
+ Data32 = MmioRead32 (PciBaseAddress + PciReg);
+ break;
+
+ case PCR_ADDR_TYPE:
+ Status = PchPcrRead32 (
+ Desc->Address.Data.Pcr.Fields.Pid,
+ Desc->Address.Data.Pcr.Fields.Offset,
+ &Data32
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ default:
+ Data32 = 0;
+ DEBUG ((DEBUG_ERROR, "Address type for eSPI SMI is invalid \n"));
+ ASSERT (FALSE);
+ break;
+ }
+
+ if ((Data32 & Desc->SourceIsActiveAndMask) == Desc->SourceIsActiveValue) {
+ Active = TRUE;
+ }
+
+ return Active;
+}
+
+/**
+ Insert a handler into the corresponding linked list based on EspiSmiType
+
+ @param[in] DispatchFunction The callback to execute
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE to determine which linked list to use
+ @param[out] DispatchHandle The link to the record in the database
+
+ @retval EFI_SUCCESS Record was successfully inserted into master database
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate pool to insert record
+**/
+STATIC
+EFI_STATUS
+InsertEspiRecord (
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN ESPI_SMI_TYPE EspiSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_SMI_RECORD *Record;
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (ESPI_SMI_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SetMem (Record, sizeof (ESPI_SMI_RECORD), 0);
+
+ Record->Callback = DispatchFunction;
+ Record->Signature = ESPI_SMI_RECORD_SIGNATURE;
+
+ InsertTailList (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], &Record->Link);
+ EspiSmiClearStatus (EspiSmiType);
+ EspiSmiEnableSource (EspiSmiType);
+
+ ++mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType];
+
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This callback is registered to PchSmiDispatch
+
+ @param[in] DispatchHandle Used to determine which source have been triggered
+**/
+VOID
+EspiSmiCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *PchSmiRecord;
+ ESPI_TOP_LEVEL_TYPE EspiTopLevelType;
+ ESPI_SMI_TYPE EspiSmiType;
+ ESPI_SMI_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ PchSmiRecord = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ if (PchSmiRecord->PchSmiType == PchTcoSmiLpcBiosWpType) {
+ EspiTopLevelType = EspiBiosWrProtect;
+ } else if (PchSmiRecord->PchSmiType == PchSmiSerialIrqType) {
+ EspiTopLevelType = EspiSerialIrq;
+ } else {
+ DEBUG ((DEBUG_ERROR, "EspiSmiCallback was dispatched with a wrong DispatchHandle"));
+ ASSERT (FALSE);
+ return;
+ }
+
+ for (EspiSmiType = mEspiSmiInstance.Barrier[EspiTopLevelType].Start; EspiSmiType <= mEspiSmiInstance.Barrier[EspiTopLevelType].End; ++EspiSmiType) {
+ if (!EspiSmiSourceIsActive (EspiSmiType)) {
+ continue;
+ }
+ //
+ // The source is active, so walk the callback database and dispatch
+ //
+ if (!IsListEmpty (&mEspiSmiInstance.CallbackDataBase[EspiSmiType])) {
+ //
+ // We have children registered w/ us -- continue
+ //
+ LinkInDb = GetFirstNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType]);
+
+ while (!IsNull (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb)) {
+ RecordInDb = ESPI_RECORD_FROM_LINK (LinkInDb);
+
+ //
+ // RecordInDb->Link might be removed (unregistered) by Callback function, and then the
+ // system will hang in ASSERT() while calling GetNextNode().
+ // To prevent the issue, we need to get next record in DB here (before Callback function).
+ //
+ LinkInDb = GetNextNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], &RecordInDb->Link);
+
+ //
+ // Callback
+ //
+ if (RecordInDb->Callback != NULL) {
+ RecordInDb->Callback ((EFI_HANDLE) &RecordInDb->Link);
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+ //
+ // Finish walking the linked list for the EspiSmiType, so clear status
+ //
+ EspiSmiClearStatus (EspiSmiType);
+ }
+}
+
+//
+// EspiBiosWp srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescEspiBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ S_PCH_ESPI_PCBC,
+ N_PCH_ESPI_PCBC_LE
+ }
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ S_PCH_ESPI_PCBC,
+ N_PCH_ESPI_PCBC_BWPDS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ This function will register EspiSmiCallback with mSrcDescEspiBiosWp source decriptor
+ This function make sure there is only one BIOS WP SMI handler is registered.
+ While any ESPI sub BIOS WP SMI type is registered, all the BIOS WP SMI
+ will go to callback function EspiSmiCallback first, and then dispatchs the callbacks
+ recorded in mEspiSmiInstance.
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval others Registration failed
+**/
+STATIC
+EFI_STATUS
+RegisterBiosWrProtectIfNull (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect] == NULL) {
+ Status = PchSmiRecordInsert (
+ &mSrcDescEspiBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) EspiSmiCallback,
+ PchTcoSmiLpcBiosWpType,
+ &mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to register BIOS WP SMI handler \n"));
+ return Status;
+ }
+ Record = DATABASE_RECORD_FROM_LINK (mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect]);
+ Record->ClearSource = PchTcoSmiClearSource;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will register EspiSmiCallback with mSrcDescSerialIrq source decriptor
+ This function make sure there is only one Serial IRQ SMI handler is registered.
+ While any ESPI sub Serial IRQ SMI type is registered, all the Serial IRQ SMI
+ will go to callback function EspiSmiCallback first, and then dispatchs the callbacks
+ recorded in mEspiSmiInstance.
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval others Registration failed
+**/
+STATIC
+EFI_STATUS
+RegisterSerialIrqIfNull (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiSerialIrq] == NULL) {
+ Status = PchSmiRecordInsert (
+ &mSrcDescSerialIrq,
+ (PCH_SMI_CALLBACK_FUNCTIONS) EspiSmiCallback,
+ PchSmiSerialIrqType,
+ &mEspiSmiInstance.PchSmiEspiHandle[EspiSerialIrq]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to register Serial IRQ SMI handler \n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Installs and initialize this protocol
+
+ @param[in] ImageHandle Not used
+
+ @retval EFI_SUCCESS Installation succeed
+ @retval others Installation failed
+**/
+EFI_STATUS
+EFIAPI
+InstallEspiSmi (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_SMI_TYPE EspiType;
+
+ //
+ // InitializeListHead for mEspiSmiInstance.CallBackDataBase[EspiTopLevelTypeMax]
+ //
+ for (EspiType = 0; EspiType < EspiSmiTypeMax; ++EspiType) {
+ InitializeListHead (&mEspiSmiInstance.CallbackDataBase[EspiType]);
+ }
+
+ //
+ // Install EfiEspiSmiDispatchProtocol
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mEspiSmiInstance.Handle,
+ &gPchEspiSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mEspiSmiInstance.PchEspiSmiDispatchProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to install eSPI SMI Dispatch Protocol \n"));
+ ASSERT (FALSE);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Protect event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrProtectRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterBiosWrProtectIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, BiosWrProtect, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Report event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrReportRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, BiosWrReport, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, PcNonFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, PcFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, VwNonFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, VwFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, FlashNonFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, FlashFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Link Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+LnkType1ErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, LnkType1Err, DispatchHandle);
+}
+
+//
+// EspiSlave srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescEspiSlave = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_ESPI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ESPI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ESPI
+ }
+};
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a eSPI slave SMI
+ This routine will also lock down ESPI_SMI_LOCK bit after registration and prevent
+ this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED The ESPI_SMI_LOCK is set and register is blocked.
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+EspiSlaveSmiRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GenPmConA;
+ UINTN PmcBaseAddress;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // If ESPI_SMI_LOCK is set, the register is blocked.
+ //
+ PmcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ GenPmConA = MmioRead32 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_A);
+ if (GenPmConA & B_PCH_PMC_GEN_PMCON_A_ESPI_SMI_LOCK) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // @note: This service doesn't utilize the data base of mEspiSmiInstance.
+ // While SMI is triggered it directly goes to the registing DispatchFunction
+ // instead of EspiSmiCallback.
+ //
+ Status = PchSmiRecordInsert (
+ &mSrcDescEspiSlave,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchEspiSmiEspiSlaveType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescEspiSlave);
+ PchSmmEnableSource (&mSrcDescEspiSlave);
+
+ //
+ // Lock down the ESPI_SMI_LOCK after ESPI SMI is enabled.
+ //
+ MmioOr8 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_A, B_PCH_PMC_GEN_PMCON_A_ESPI_SMI_LOCK);
+ //
+ // Keep the DispatchHandle which will be used for unregister function.
+ //
+ mEspiSmiInstance.PchSmiEspiHandle[EspiPmc] = *DispatchHandle;
+
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+ @retval EFI_ACCESS_DENIED DispatchHandle is not allowed to unregistered
+**/
+EFI_STATUS
+EFIAPI
+EspiSmiUnRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_TOP_LEVEL_TYPE EspiTopLevelType;
+ ESPI_SMI_TYPE EspiSmiType;
+ BOOLEAN SafeToDisable;
+ LIST_ENTRY *LinkInDb;
+ ESPI_SMI_RECORD *RecordPointer;
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (((LIST_ENTRY *) DispatchHandle)->ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For DispatchHandle belongs to Espi Slave SMI, refuses the request of unregistration.
+ //
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiPmc] == DispatchHandle) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed for ESPI Slave SMI handle! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Iterate through all the database to find the record
+ //
+ for (EspiSmiType = 0; EspiSmiType < EspiSmiTypeMax; ++EspiSmiType) {
+ LinkInDb = GetFirstNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType]);
+
+ while (!IsNull (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb)) {
+ if (LinkInDb != (LIST_ENTRY *) DispatchHandle) {
+ LinkInDb = GetNextNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb);
+
+ } else {
+ //
+ // Found the source to be from this list
+ //
+ RemoveEntryList (LinkInDb);
+ RecordPointer = (ESPI_RECORD_FROM_LINK (LinkInDb));
+
+ if (mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] != 0) {
+ if (--mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] == 0) {
+ EspiSmiDisableSource (EspiSmiType);
+ }
+ }
+
+ Status = gSmst->SmmFreePool (RecordPointer);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ }
+
+ goto EspiSmiUnRegisterEnd;
+ }
+ }
+ }
+ //
+ // If the code reach here, the handle passed in cannot be found
+ //
+ DEBUG ((DEBUG_ERROR, "eSPI SMI handle is not in record database \n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+
+EspiSmiUnRegisterEnd:
+
+ //
+ // Unregister and clear the handle from PchSmiDispatch
+ //
+ for (EspiTopLevelType = 0; EspiTopLevelType < EspiTopLevelTypeMax; ++EspiTopLevelType) {
+ SafeToDisable = TRUE;
+ //
+ // Checks all the child events that belongs to a top level status in PMC
+ //
+ for (EspiSmiType = mEspiSmiInstance.Barrier[EspiTopLevelType].Start; EspiSmiType <= mEspiSmiInstance.Barrier[EspiTopLevelType].End; ++EspiSmiType) {
+ if (mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] != 0) {
+ SafeToDisable = FALSE;
+ }
+ }
+ //
+ // Finally, disable the top level event in PMC
+ //
+ if (SafeToDisable) {
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType] != NULL) {
+ Status = PchSmmCoreUnRegister (NULL, mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType]);
+ ASSERT_EFI_ERROR (Status);
+ mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType] = NULL;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h
new file mode 100644
index 0000000000..2e4f407181
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h
@@ -0,0 +1,337 @@
+/** @file
+ eSPI SMI Dispatch header
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCH_SMM_ESPI_H_
+#define _PCH_SMM_ESPI_H_
+
+#include "PchSmmHelpers.h"
+
+#define ESPI_SMI_INSTANCE_SIGNATURE SIGNATURE_32 ('E', 'S', 'P', 'I')
+#define ESPI_SMI_RECORD_SIGNATURE SIGNATURE_32 ('E', 'S', 'R', 'C')
+
+#define ESPI_INSTANCE_FROM_THIS(_this) CR (_this, ESPI_SMI_INSTANCE, EfiEspiSmiDispatchProtocol, ESPI_SMI_INSTANCE_SIGNATURE)
+#define ESPI_RECORD_FROM_LINK(_link) CR (_link, ESPI_SMI_RECORD, Link, ESPI_SMI_RECORD_SIGNATURE)
+
+typedef enum {
+ EspiBiosWrProtect, ///< BIOS Write Protect
+ EspiSerialIrq, ///< eSPI Master Asserted SMI
+ EspiPmc, ///< eSPI PMC SMI
+ EspiTopLevelTypeMax
+} ESPI_TOP_LEVEL_TYPE;
+
+typedef enum {
+ BiosWrProtect, ///< BIOS Write Protect
+ BiosWrReport, ///< Peripheral Channel BIOS Write Protect
+ PcNonFatalErr, ///< Peripheral Channel Non Fatal Error
+ PcFatalErr, ///< Peripheral Channel Fatal Error
+ VwNonFatalErr, ///< Virtual Wire Non Fatal Error
+ VwFatalErr, ///< Virtual Wire Fatal Error
+ FlashNonFatalErr, ///< Flash Channel Non Fatal Error
+ FlashFatalErr, ///< Flash Channel Fatal Error
+ LnkType1Err, ///< Link Error
+ EspiSlaveSmi, ///< Espi Slave SMI
+ EspiSmiTypeMax
+} ESPI_SMI_TYPE;
+
+///
+/// This is used to classify ESPI_SMI_TYPE to ESPI_TOP_LEVEL_TYPE.
+/// Used during dispatching and unregistering
+///
+typedef struct {
+ ESPI_SMI_TYPE Start;
+ ESPI_SMI_TYPE End;
+} ESPI_SMI_TYPE_BARRIER;
+
+typedef struct _ESPI_SMI_INSTANCE {
+ ///
+ /// Signature associated with this instance
+ ///
+ UINT32 Signature;
+ ///
+ /// EFI_HANDLE acquired when installing PchEspiSmiDispatchProtocol
+ ///
+ EFI_HANDLE Handle;
+ ///
+ /// The protocol to register or unregister eSPI SMI callbacks
+ ///
+ PCH_ESPI_SMI_DISPATCH_PROTOCOL PchEspiSmiDispatchProtocol;
+ ///
+ /// The handle acquired when registering eSPI SMI callback to PchSmiDispatch
+ ///
+ EFI_HANDLE PchSmiEspiHandle[EspiTopLevelTypeMax];
+ ///
+ /// The linked list for record database.
+ ///
+ LIST_ENTRY CallbackDataBase[EspiSmiTypeMax];
+ ///
+ /// This is an internal counter to track the number of eSPI master events have been registered.
+ /// When unregistering, we can disable the SMI if the counter is zero
+ ///
+ UINTN EspiSmiEventCounter[EspiSmiTypeMax];
+ ///
+ /// Instance of barrier
+ ///
+ CONST ESPI_SMI_TYPE_BARRIER Barrier[EspiTopLevelTypeMax];
+} ESPI_SMI_INSTANCE;
+
+typedef struct _ESPI_DESCRIPTOR {
+ PCH_SMM_ADDRESS Address;
+ UINT32 SourceIsActiveAndMask;
+ UINT32 SourceIsActiveValue;
+ UINT32 ClearStatusAndMask;
+ UINT32 ClearStatusOrMask;
+} ESPI_DESCRIPTOR;
+
+///
+/// A simple record to store the callbacks associated with an eSPI SMI source
+///
+typedef struct _ESPI_SMI_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ PCH_ESPI_SMI_DISPATCH_CALLBACK Callback;
+} ESPI_SMI_RECORD;
+
+/**
+ Installs and initialize this protocol
+
+ @param[in] ImageHandle Not used
+
+ @retval EFI_SUCCESS Installation succeed
+ @retval others Installation failed
+**/
+EFI_STATUS
+EFIAPI
+InstallEspiSmi (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Protect event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrProtectRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Report event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrReportRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Link Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+LnkType1ErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a eSPI slave SMI
+ NOTE: The register function is not available when the ESPI_SMI_LOCK bit is set.
+ This runtine will also lock donw ESPI_SMI_LOCK bit after registration and
+ prevent this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED The ESPI_SMI_LOCK is set and register is blocked.
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+EspiSlaveSmiRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+ @retval EFI_ACCESS_DENIED DispatchHandle is not allowed to unregistered
+**/
+EFI_STATUS
+EFIAPI
+EspiSmiUnRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
new file mode 100644
index 0000000000..fd79538d3a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
@@ -0,0 +1,49 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+
+//
+// Structure for GPI SMI is a template which needs to have
+// GPI Smi bit offset and Smi Status & Enable registers updated (accordingly
+// to choosen group and pad number) after adding it to SMM Callback database
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC PCH_GPI_SOURCE_DESC_TEMPLATE = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ GPIO_ADDR_TYPE, {0x0}
+ },
+ S_PCH_GPIO_GP_SMI_EN, 0x0,
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ GPIO_ADDR_TYPE, {0x0}
+ },
+ S_PCH_GPIO_GP_SMI_STS, 0x0,
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPIO_SMI
+ }
+};
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
new file mode 100644
index 0000000000..fea1ac9165
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
@@ -0,0 +1,333 @@
+/** @file
+ Helper functions for PCH SMM dispatcher.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+
+///
+/// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+///
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = TRUE;
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->En[DescIndex].Bit != Src2->En[DescIndex].Bit ||
+ Src1->En[DescIndex].Reg.Type != Src2->En[DescIndex].Reg.Type ||
+ Src1->En[DescIndex].Reg.Data.raw != Src2->En[DescIndex].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+ @param[in] BitDesc Pointer to the PCH SMI bit descriptor
+ @param[in] Src Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The bit desc is equal to any of the enables in source descriptor
+ @retval FALSE The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+ CONST IN PCH_SMM_BIT_DESC *BitDesc,
+ CONST IN PCH_SMM_SOURCE_DESC *Src
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = FALSE;
+
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+ if ((BitDesc->Reg.Type == Src->En[DescIndex].Reg.Type) &&
+ (BitDesc->Reg.Data.raw == Src->En[DescIndex].Reg.Data.raw) &&
+ (BitDesc->Bit == Src->En[DescIndex].Bit)) {
+ IsEqual = TRUE;
+ break;
+ }
+ }
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = TRUE;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->Sts[DescIndex].Bit != Src2->Sts[DescIndex].Bit ||
+ Src1->Sts[DescIndex].Reg.Type != Src2->Sts[DescIndex].Reg.Type ||
+ Src1->Sts[DescIndex].Reg.Data.raw != Src2->Sts[DescIndex].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
+}
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+ @param[in] SciEn Indicate if SCI is enabled or not
+ @param[in] SmiEnValue Value from R_PCH_SMI_EN
+ @param[in] SmiStsValue Value from R_PCH_SMI_STS
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ CONST IN PCH_SMM_SOURCE_DESC *Src,
+ CONST IN BOOLEAN SciEn,
+ CONST IN UINT32 SmiEnValue,
+ CONST IN UINT32 SmiStsValue
+ )
+{
+ UINTN DescIndex;
+
+ ///
+ /// This source is dependent on SciEn, and SciEn == 1. An ACPI OS is present,
+ /// so we shouldn't do anything w/ this source until SciEn == 0.
+ ///
+ if ((Src->Flags == PCH_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
+ return FALSE;
+ }
+
+ ///
+ /// Checking top level SMI status. If the status is not active, return false immediately
+ ///
+ if (!IS_BIT_DESC_NULL (Src->PmcSmiSts)) {
+ if ((Src->PmcSmiSts.Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->PmcSmiSts.Reg.Data.acpi == R_PCH_SMI_STS) &&
+ ((SmiStsValue & (1u << Src->PmcSmiSts.Bit)) == 0)) {
+ return FALSE;
+ }
+ }
+
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (Src->En[DescIndex])) {
+ if ((Src->En[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->En[DescIndex].Reg.Data.acpi == R_PCH_SMI_EN) &&
+ ((SmiEnValue & (1u << Src->En[DescIndex].Bit)) == 0)) {
+ return FALSE;
+ } else if (ReadBitDesc (&Src->En[DescIndex]) == 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (Src->Sts[DescIndex])) {
+ if ((Src->Sts[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->Sts[DescIndex].Reg.Data.acpi == R_PCH_SMI_STS) &&
+ ((SmiStsValue & (1u << Src->Sts[DescIndex].Bit)) == 0)) {
+ return FALSE;
+ } else if (ReadBitDesc (&Src->Sts[DescIndex]) == 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ ///
+ /// Set enables to 1 by writing a 1
+ ///
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+ WriteBitDesc (&SrcDesc->En[DescIndex], 1, FALSE);
+ }
+ }
+ ///
+ /// Clear statuses to 0 by writing a 1
+ ///
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+ WriteBitDesc (&SrcDesc->En[DescIndex], 0, FALSE);
+ }
+ }
+}
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+ BOOLEAN IsSet;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ ///
+ /// Write the bit
+ ///
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+
+ ///
+ /// Don't return until the bit actually clears.
+ ///
+ IsSet = TRUE;
+ while (IsSet) {
+ IsSet = ReadBitDesc (&SrcDesc->Sts[DescIndex]);
+ ///
+ /// IsSet will eventually clear -- or else we'll have
+ /// an infinite loop.
+ ///
+ }
+ }
+ }
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
new file mode 100644
index 0000000000..44a8936790
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
@@ -0,0 +1,162 @@
+/** @file
+ Helper functions for PCH SMM
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef PCH_SMM_HELPERS_H
+#define PCH_SMM_HELPERS_H
+
+#include "PchSmm.h"
+#include "PchxSmmHelpers.h"
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+//
+
+/**
+ Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ );
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+ @param[in] BitDesc Pointer to the PCH SMI bit descriptor
+ @param[in] Src Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The bit desc is equal to any of the enables in source descriptor
+ @retval FALSE The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+ CONST IN PCH_SMM_BIT_DESC *BitDesc,
+ CONST IN PCH_SMM_SOURCE_DESC *Src
+ );
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+ @param[in] SciEn Indicate if SCI is enabled or not
+ @param[in] SmiEnValue Value from R_PCH_SMI_EN
+ @param[in] SmiStsValue Value from R_PCH_SMI_STS
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ CONST IN PCH_SMM_SOURCE_DESC *Src,
+ CONST IN BOOLEAN SciEn,
+ CONST IN UINT32 SmiEnValue,
+ CONST IN UINT32 SmiStsValue
+ );
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
new file mode 100644
index 0000000000..324eaeb7e8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
@@ -0,0 +1,702 @@
+/** @file
+ File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/PchSmmPeriodicTimerControl.h>
+
+//
+// There is only one instance for PeriodicTimerCommBuffer.
+// It's safe in SMM since there is no re-entry for the function.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_PERIODIC_TIMER_CONTEXT mPchPeriodicTimerCommBuffer;
+
+typedef enum {
+ PERIODIC_TIMER= 0,
+ SWSMI_TIMER,
+ NUM_TIMERS
+} SUPPORTED_TIMER;
+
+typedef struct _TIMER_INTERVAL {
+ UINT64 Interval;
+ UINT8 AssociatedTimer;
+} TIMER_INTERVAL;
+
+#define NUM_INTERVALS 8
+
+//
+// Time constants, in 100 nano-second units
+//
+#define TIME_64s 640000000 ///< 64 s
+#define TIME_32s 320000000 ///< 32 s
+#define TIME_16s 160000000 ///< 16 s
+#define TIME_8s 80000000 ///< 8 s
+#define TIME_64ms 640000 ///< 64 ms
+#define TIME_32ms 320000 ///< 32 ms
+#define TIME_16ms 160000 ///< 16 ms
+#define TIME_1_5ms 15000 ///< 1.5 ms
+
+typedef enum {
+ INDEX_TIME_64s = 0,
+ INDEX_TIME_32s,
+ INDEX_TIME_16s,
+ INDEX_TIME_8s,
+ INDEX_TIME_64ms,
+ INDEX_TIME_32ms,
+ INDEX_TIME_16ms,
+ INDEX_TIME_1_5ms,
+ INDEX_TIME_MAX
+} TIMER_INTERVAL_INDEX;
+
+static TIMER_INTERVAL mSmmPeriodicTimerIntervals[NUM_INTERVALS] = {
+ {
+ TIME_64s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_32s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_16s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_8s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_64ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_32ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_16ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_1_5ms,
+ SWSMI_TIMER
+ },
+};
+
+typedef struct _TIMER_INFO {
+ UINTN NumChildren; ///< number of children using this timer
+ UINT64 MinReqInterval; ///< minimum interval required by children
+ UINTN CurrentSetting; ///< interval this timer is set at right now (index into interval table)
+} TIMER_INFO;
+
+GLOBAL_REMOVE_IF_UNREFERENCED TIMER_INFO mTimers[NUM_TIMERS];
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mTIMER_SOURCE_DESCS[NUM_TIMERS] = {
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_PERIODIC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PERIODIC
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PERIODIC
+ }
+ },
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_SWSMI_TMR
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SWSMI_TMR
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SWSMI_TMR
+ }
+ }
+};
+
+/**
+ Program Smm Periodic Timer
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Convert the dispatch context to the timer interval, this function will assert if then either:
+ (1) The context contains an invalid interval
+ (2) The timer interval table is corrupt
+
+ @param[in] DispatchContext The pointer to the Dispatch Context
+
+ @retval TIMER_INTERVAL The timer interval of input dispatch context
+**/
+TIMER_INTERVAL *
+ContextToTimerInterval (
+ IN PCH_SMM_CONTEXT *DispatchContext
+ )
+{
+ UINTN loopvar;
+
+ ///
+ /// Determine which timer this child is using
+ ///
+ for (loopvar = 0; loopvar < NUM_INTERVALS; loopvar++) {
+ if (((DispatchContext->PeriodicTimer.SmiTickInterval == 0) &&
+ (DispatchContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
+ (DispatchContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)) {
+ return &mSmmPeriodicTimerIntervals[loopvar];
+ }
+ }
+ ///
+ /// If this assertion fires, then either:
+ /// (1) the context contains an invalid interval
+ /// (2) the timer interval table is corrupt
+ ///
+ ASSERT (FALSE);
+
+ return NULL;
+}
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ///
+ /// Figure out which timer the child is requesting and
+ /// send back the source description
+ ///
+ TimerInterval = ContextToTimerInterval (DispatchContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ CopyMem (
+ (VOID *) SrcDesc,
+ (VOID *) (&mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+
+ ///
+ /// Program the value of the interval into hardware
+ ///
+ PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *HwContext
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ TimerInterval = ContextToTimerInterval (&Record->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+ ///
+ /// Ignore the hardware context. It's not required for this protocol.
+ /// Instead, just increment the child's context.
+ /// Update the elapsed time w/ the data from our tables
+ ///
+ Record->MiscData.ElapsedTime += mTimers[TimerInterval->AssociatedTimer].MinReqInterval;
+ *HwContext = Record->ChildContext;
+}
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *HwContext,
+ IN PCH_SMM_CONTEXT *ChildContext
+ )
+{
+ DATABASE_RECORD *Record;
+ Record = DATABASE_RECORD_FROM_CHILDCONTEXT (ChildContext);
+
+ if (Record->MiscData.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
+ ///
+ /// For EDKII, the ElapsedTime is reset when PeriodicTimerGetCommBuffer
+ ///
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ )
+{
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ mPchPeriodicTimerCommBuffer.ElapsedTime = Record->MiscData.ElapsedTime;
+
+ ///
+ /// For EDKII, the ElapsedTime is reset here
+ ///
+ Record->MiscData.ElapsedTime = 0;
+
+ ///
+ /// Return the CommBuffer
+ ///
+ *CommBuffer = (VOID *) &mPchPeriodicTimerCommBuffer;
+ *CommBufferSize = sizeof (EFI_SMM_PERIODIC_TIMER_CONTEXT);
+}
+
+/**
+ Program Smm Periodic Timer
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ SUPPORTED_TIMER Timer;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ TIMER_INTERVAL *TimerInterval;
+ UINT8 GenPmConA;
+ UINT8 GenPmConB;
+ UINTN PciPmcRegBase;
+
+ PciPmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+
+ ///
+ /// Find the minimum required interval for each timer
+ ///
+ for (Timer = 0; Timer < NUM_TIMERS; Timer++) {
+ mTimers[Timer].MinReqInterval = ~ (UINT64) 0x0;
+ mTimers[Timer].NumChildren = 0;
+ }
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ ///
+ /// This child is registerd with the PeriodicTimer protocol
+ ///
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ Timer = TimerInterval->AssociatedTimer;
+ if (Timer < 0 || Timer >= NUM_TIMERS) {
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ return;
+ }
+
+ if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
+ mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
+ }
+
+ mTimers[Timer].NumChildren++;
+ }
+
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ ///
+ /// Program the hardware
+ ///
+ if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
+ GenPmConA = MmioRead8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A);
+ GenPmConA &= (UINT8) ~B_PCH_PMC_GEN_PMCON_A_PER_SMI_SEL;
+ switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
+ case TIME_64s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_64S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
+ break;
+
+ case TIME_32s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_32S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
+ break;
+
+ case TIME_16s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_16S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
+ break;
+
+ case TIME_8s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_8S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ MmioWrite8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A, GenPmConA);
+ ///
+ /// Restart the timer here, just need to clear the SMI
+ ///
+ if (SrcDesc->Sts[0].Bit == N_PCH_SMI_STS_PERIODIC) {
+ PchSmmClearSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ }
+ } else {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ }
+
+ if (mTimers[SWSMI_TIMER].NumChildren > 0) {
+ ///
+ /// ICH9, ICH10 and PCH share the same bit positions for SW SMI Rate settings
+ ///
+ GenPmConB = MmioRead8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B);
+ //
+ // Don't clear B_PCH_PMC_GEN_PMCON_B_PWR_FLR by accident since it's RW/1C.
+ //
+ GenPmConB &= ~B_PCH_PMC_GEN_PMCON_B_PWR_FLR;
+
+ GenPmConB &= ~B_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL;
+ switch (mTimers[SWSMI_TIMER].MinReqInterval) {
+ case TIME_64ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_64MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_64ms;
+ break;
+
+ case TIME_32ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_32MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_32ms;
+ break;
+
+ case TIME_16ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_16MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_16ms;
+ break;
+
+ case TIME_1_5ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_1_5MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// SWSMI_RATE_SEL BIT (PMC PCI offset A4h[7:6]) bits are in RTC well
+ ///
+ MmioWrite8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B, GenPmConB);
+
+ ///
+ /// Restart the timer here, need to disable, clear, then enable to restart this timer
+ ///
+ if (SrcDesc->Sts[0].Bit == N_PCH_SMI_STS_SWSMI_TMR) {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ PchSmmClearSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ PchSmmEnableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ }
+ } else {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ }
+}
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ )
+{
+ TIMER_INTERVAL *IntervalPointer;
+
+ ASSERT (SmiTickInterval != NULL);
+
+ IntervalPointer = (TIMER_INTERVAL *) *SmiTickInterval;
+
+ if (IntervalPointer == NULL) {
+ ///
+ /// The first time child requesting an interval
+ ///
+ IntervalPointer = &mSmmPeriodicTimerIntervals[0];
+ } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1]) {
+ ///
+ /// At end of the list
+ ///
+ IntervalPointer = NULL;
+ } else {
+ if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
+ (IntervalPointer < &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1])
+ ) {
+ ///
+ /// Get the next interval in the list
+ ///
+ IntervalPointer++;
+ } else {
+ ///
+ /// Input is out of range
+ ///
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (IntervalPointer != NULL) {
+ *SmiTickInterval = &IntervalPointer->Interval;
+ } else {
+ *SmiTickInterval = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+
+/**
+ Check if the handle is in type of PeriodicTimer
+
+ @retval TRUE The handle is in type of PeriodicTimer.
+ @retval FALSE The handle is not in type of PeriodicTimer.
+**/
+BOOLEAN
+IsSmmPeriodicTimerHandle (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ if (DispatchHandle == (EFI_HANDLE) LinkInDb) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ return TRUE;
+ }
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, LinkInDb);
+ }
+ return FALSE;
+}
+
+/**
+ Pause SMM periodic timer callback function.
+
+ This function disable the SMI enable of SMI timer according to the DispatchHandle,
+ which is returned by SMM periodic timer callback registration.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlPause (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+ TIMER_INTERVAL *TimerInterval;
+
+ if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ TimerInterval = NULL;
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer]);
+ return EFI_SUCCESS;
+}
+
+/**
+ Resume SMM periodic timer callback function.
+
+ This function enable the SMI enable of SMI timer according to the DispatchHandle,
+ which is returned by SMM periodic timer callback registration.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlResume (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+ TIMER_INTERVAL *TimerInterval;
+
+ if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ TimerInterval = NULL;
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PchSmmEnableSource (&mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer]);
+ return EFI_SUCCESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL mPchSmmPeriodicTimerControlProtocol = {
+ PchSmmPeriodicTimerControlPause,
+ PchSmmPeriodicTimerControlResume
+};
+
+/**
+ Install PCH SMM periodic timer control protocol
+
+ @param[in] Handle handle for this driver
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install protocol interface
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchSmmPeriodicTimerControlGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchSmmPeriodicTimerControlProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
new file mode 100644
index 0000000000..404d2a31bc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
@@ -0,0 +1,96 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Power Button dispatch protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PchSmmHelpers.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC POWER_BUTTON_SOURCE_DESC = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_EN}
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_PWRBTN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_STS}
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_PWRBTN
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT32 GenPmConA;
+ UINTN PmcBaseAddress;
+
+ PmcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ GenPmConA = MmioRead32 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_A);
+ if ((GenPmConA & B_PCH_PMC_GEN_PMCON_A_PWRBTN_LVL) != 0) {
+ Context->PowerButton.Phase = EfiPowerButtonExit;
+ } else {
+ Context->PowerButton.Phase = EfiPowerButtonEntry;
+ }
+}
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->PowerButton.Phase == Context2->PowerButton.Phase);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
new file mode 100644
index 0000000000..c285c677f1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
@@ -0,0 +1,169 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+
+#include <Protocol/SmmCpu.h>
+//
+// There is only one instance for SwCommBuffer.
+// It's safe in SMM since there is no re-entry for the function.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SW_CONTEXT mPchSwCommBuffer;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC SW_SOURCE_DESC = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_APMC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_APM
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_APM
+ }
+};
+
+/**
+ Get the Software Smi value
+
+ @param[in] Record No use
+ @param[out] Context The context that includes Software Smi value to be filled
+
+**/
+VOID
+EFIAPI
+SwGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT8 ApmCnt;
+
+ ApmCnt = IoRead8 ((UINTN) R_PCH_APM_CNT);
+
+ Context->Sw.SwSmiInputValue = ApmCnt;
+}
+
+/**
+ Check whether software SMI value of two contexts match
+
+ @param[in] Context1 Context 1 that includes software SMI value 1
+ @param[in] Context2 Context 2 that includes software SMI value 2
+
+ @retval FALSE Software SMI value match
+ @retval TRUE Software SMI value don't match
+**/
+BOOLEAN
+EFIAPI
+SwCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue);
+}
+
+/**
+ Gather the CommBuffer information of SmmSwDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+SwGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_SAVE_STATE_IO_INFO SmiIoInfo;
+ UINTN Index;
+
+ ASSERT (Record->ProtocolType == SwType);
+
+ mPchSwCommBuffer.CommandPort = IoRead8 (R_PCH_APM_CNT);
+ mPchSwCommBuffer.DataPort = IoRead8 (R_PCH_APM_STS);
+
+ //
+ // Try to find which CPU trigger SWSMI
+ //
+ mPchSwCommBuffer.SwSmiCpuIndex = 0;
+ for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
+ Status = mSmmCpuProtocol->ReadSaveState (
+ mSmmCpuProtocol,
+ sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+ EFI_SMM_SAVE_STATE_REGISTER_IO,
+ Index,
+ &SmiIoInfo
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (SmiIoInfo.IoPort == R_PCH_APM_CNT) {
+ //
+ // Find matched CPU.
+ //
+ mPchSwCommBuffer.SwSmiCpuIndex = Index;
+ break;
+ }
+ }
+
+ ///
+ /// Return the CommBuffer
+ ///
+ *CommBuffer = (VOID *) &mPchSwCommBuffer;
+ *CommBufferSize = sizeof (EFI_SMM_SW_CONTEXT);
+}
+
+/**
+ Init required protocol for Pch Sw Dispatch protocol.
+
+
+**/
+VOID
+PchSwDispatchInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ //
+ // Locate PI SMM CPU protocol
+ //
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
new file mode 100644
index 0000000000..523cea27aa
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
@@ -0,0 +1,235 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+
+#define PROGRESS_CODE_S3_SUSPEND_END PcdGet32 (PcdProgressCodeS3SuspendEnd)
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC SX_SOURCE_DESC = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_ON_SLP_EN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ON_SLP_EN
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ON_SLP_EN
+ }
+};
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT32 Pm1Cnt;
+
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ ///
+ /// By design, the context phase will always be ENTRY
+ ///
+ Context->Sx.Phase = SxEntry;
+
+ ///
+ /// Map the PM1_CNT register's SLP_TYP bits to the context type
+ ///
+ switch (Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) {
+ case V_PCH_ACPI_PM1_CNT_S0:
+ Context->Sx.Type = SxS0;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S1:
+ Context->Sx.Type = SxS1;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S3:
+ Context->Sx.Type = SxS3;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S4:
+ Context->Sx.Type = SxS4;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S5:
+ Context->Sx.Type = SxS5;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->Sx.Type == Context2->Sx.Type);
+}
+
+/**
+ For each PCIE RP clear PME SCI status and disable SCI, then PCIEXP_WAKE_STS from PMC.
+ This prevents platform from waking more than one time due to a single PCIE wake event.
+ Normally it's up to OS to clear SCI statuses. But in a scenario where platform wakes
+ and goes to S5 instead of booting to OS, the SCI status would remain set and would trigger another wake.
+**/
+VOID
+ClearPcieSci (
+ VOID
+ )
+{
+ UINT32 MaxPorts;
+ UINT32 RpIndex;
+ UINTN RpBase;
+
+ MaxPorts = GetPchMaxPciePortNum ();
+ for (RpIndex = 0; RpIndex < MaxPorts; RpIndex++) {
+ RpBase = PchPcieBase (RpIndex);
+ if (MmioRead16 (RpBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF) {
+ MmioAnd8 ((RpBase + R_PCH_PCIE_MPC + 3), (UINT8)~((UINT8)(B_PCH_PCIE_MPC_PMCE >> 24)));
+ MmioWrite32 (RpBase + R_PCH_PCIE_SMSCS, B_PCH_PCIE_SMSCS_PMCS);
+ }
+ }
+ IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS);
+}
+
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+
+
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ )
+{
+ UINT32 Pm1Cnt;
+ UINT32 PchPwrmBase;
+
+ ClearPcieSci ();
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ ///
+ /// Flush cache into memory before we go to sleep. It is necessary for S3 sleep
+ /// because we may update memory in SMM Sx sleep handlers -- the updates are in cache now
+ ///
+ AsmWbinvd ();
+
+ ///
+ /// Disable SMIs
+ ///
+ PchSmmClearSource (&SX_SOURCE_DESC);
+ PchSmmDisableSource (&SX_SOURCE_DESC);
+
+ ///
+ /// Get Power Management 1 Control Register Value
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ ///
+ /// Record S3 suspend performance data
+ ///
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
+ ///
+ /// Report status code before goto S3 sleep
+ ///
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PROGRESS_CODE_S3_SUSPEND_END);
+
+ ///
+ /// Flush cache into memory before we go to sleep.
+ ///
+ AsmWbinvd ();
+ }
+
+ ///
+ /// Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
+ ///
+ Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT), Pm1Cnt);
+
+ ///
+ /// Should only proceed if wake event is generated.
+ ///
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S1) {
+ while (((IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS))) & B_PCH_ACPI_PM1_STS_WAK) == 0x0);
+ } else {
+ CpuDeadLoop ();
+ }
+ ///
+ /// The system just went to sleep. If the sleep state was S1, then code execution will resume
+ /// here when the system wakes up.
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == 0) {
+ ///
+ /// An ACPI OS isn't present, clear the sleep information
+ ///
+ Pm1Cnt &= ~B_PCH_ACPI_PM1_CNT_SLP_TYP;
+ Pm1Cnt |= V_PCH_ACPI_PM1_CNT_S0;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT), Pm1Cnt);
+ }
+
+ PchSmmClearSource (&SX_SOURCE_DESC);
+ PchSmmEnableSource (&SX_SOURCE_DESC);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
new file mode 100644
index 0000000000..71c11ed71d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
@@ -0,0 +1,232 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm USB dispatch protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mUSB1_LEGACY = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_LEGACY_USB
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mUSB3_LEGACY = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_LEGACY_USB3
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB3
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB3
+ }
+};
+
+typedef enum {
+ PchUsbControllerLpc0 = 0,
+ PchUsbControllerXhci,
+ PchUsbControllerTypeMax
+} PCH_USB_CONTROLLER_TYPE;
+
+typedef struct {
+ UINT8 Function;
+ UINT8 Device;
+ PCH_USB_CONTROLLER_TYPE UsbConType;
+} USB_CONTROLLER;
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CONTROLLER mUsbControllersMap[] = {
+ {
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PchUsbControllerLpc0
+ },
+ {
+ PCI_FUNCTION_NUMBER_PCH_XHCI,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PchUsbControllerXhci
+ }
+};
+
+/**
+ Find the handle that best matches the input Device Path and return the USB controller type
+
+ @param[in] DevicePath Pointer to the device Path table
+ @param[out] Controller Returned with the USB controller type of the input device path
+
+ @retval EFI_SUCCESS Find the handle that best matches the input Device Path
+ @exception EFI_UNSUPPORTED Invalid device Path table or can't find any match USB device path
+ PCH_USB_CONTROLLER_TYPE The USB controller type of the input
+ device path
+**/
+EFI_STATUS
+DevicePathToSupportedController (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT PCH_USB_CONTROLLER_TYPE *Controller
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ ACPI_HID_DEVICE_PATH *AcpiNode;
+ PCI_DEVICE_PATH *PciNode;
+ EFI_DEVICE_PATH_PROTOCOL *RemaingDevicePath;
+ UINT8 UsbIndex;
+ ///
+ /// Find the handle that best matches the Device Path. If it is only a
+ /// partial match the remaining part of the device path is returned in
+ /// RemainingDevicePath.
+ ///
+ RemaingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &DevicePath,
+ &DeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DevicePath = RemaingDevicePath;
+
+ ///
+ /// Get first node: Acpi Node
+ ///
+ AcpiNode = (ACPI_HID_DEVICE_PATH *) RemaingDevicePath;
+
+ if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
+ AcpiNode->Header.SubType != ACPI_DP ||
+ DevicePathNodeLength (&AcpiNode->Header) != sizeof (ACPI_HID_DEVICE_PATH) ||
+ AcpiNode->HID != EISA_PNP_ID (0x0A03) ||
+ AcpiNode->UID != 0
+ ) {
+ return EFI_UNSUPPORTED;
+ } else {
+ ///
+ /// Get the next node: Pci Node
+ ///
+ RemaingDevicePath = NextDevicePathNode (RemaingDevicePath);
+ PciNode = (PCI_DEVICE_PATH *) RemaingDevicePath;
+ if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
+ PciNode->Header.SubType != HW_PCI_DP ||
+ DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH)
+ ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (UsbIndex = 0; UsbIndex < sizeof (mUsbControllersMap) / sizeof (USB_CONTROLLER); UsbIndex++) {
+ if ((PciNode->Device == mUsbControllersMap[UsbIndex].Device) &&
+ (PciNode->Function == mUsbControllersMap[UsbIndex].Function)) {
+ *Controller = mUsbControllersMap[UsbIndex].UsbConType;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[in] SrcDesc The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PCH_USB_CONTROLLER_TYPE Controller;
+ EFI_STATUS Status;
+
+ Status = DevicePathToSupportedController (Context->Usb.Device, &Controller);
+ ///
+ /// Either the device path passed in by the child is incorrect or
+ /// the ones stored here internally are incorrect.
+ ///
+ ASSERT_EFI_ERROR (Status);
+
+ switch (Context->Usb.Type) {
+ case UsbLegacy:
+ switch (Controller) {
+ case PchUsbControllerLpc0:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB1_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ case PchUsbControllerXhci:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB3_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case UsbWake:
+ ASSERT (FALSE);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
new file mode 100644
index 0000000000..d4f4603eea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
@@ -0,0 +1,790 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSmmHelpers.h"
+
+//
+// Help handle porting bit shifts to IA-64.
+//
+#define BIT_ZERO 0x00000001
+
+/**
+ Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Index;
+ //
+ // Install protocol interfaces.
+ //
+ for (Index = 0; Index < PCH_SMM_PROTOCOL_TYPE_MAX; Index++) {
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mPrivateData.InstallMultProtHandle,
+ mPrivateData.Protocols[Index].Guid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.Protocols[Index].Protocols.Generic
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Clear all SMIs
+ ///
+ PchSmmClearSmi ();
+
+ Status = PchSmmEnableGlobalSmiBit ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Be *really* sure to clear all SMIs
+ ///
+ PchSmmClearSmi ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Set the "global smi enable" bit
+ ///
+ SmiEn |= B_PCH_SMI_EN_GBL_SMI;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ )
+{
+ BOOLEAN EosSet;
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+ UINT16 Pm1Sts;
+ UINT32 Gpe0Sts;
+ UINT32 SmiSts;
+ UINT16 DevActSts;
+ UINT16 Tco1Sts;
+
+ Gpe0Sts = 0;
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+ if (!SciEn) {
+ ///
+ /// Clear any SMIs that double as SCIs (when SCI_EN==0)
+ ///
+ Pm1Sts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS));
+ Gpe0Sts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96));
+
+ Pm1Sts |=
+ (
+ B_PCH_ACPI_PM1_STS_WAK |
+ B_PCH_ACPI_PM1_STS_PRBTNOR |
+ B_PCH_ACPI_PM1_STS_RTC |
+ B_PCH_ACPI_PM1_STS_PWRBTN |
+ B_PCH_ACPI_PM1_STS_GBL |
+ B_PCH_ACPI_PM1_STS_TMROF
+ );
+
+ Gpe0Sts |=
+ (
+ B_PCH_ACPI_GPE0_STS_127_96_PME_B0 |
+ B_PCH_ACPI_GPE0_STS_127_96_PME |
+ B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
+ B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP |
+ B_PCH_ACPI_GPE0_STS_127_96_RI |
+ B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK |
+ B_PCH_ACPI_GPE0_STS_127_96_TC0SCI |
+ B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG |
+ B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
+ B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE
+ );
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS), (UINT16) Pm1Sts);
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96), (UINT32) Gpe0Sts);
+ }
+ ///
+ /// Clear all SMIs that are unaffected by SCI_EN
+ ///
+ SmiSts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS));
+ DevActSts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS));
+ Tco1Sts = IoRead16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS));
+
+ SmiSts |=
+ (
+ B_PCH_SMI_STS_SMBUS |
+ B_PCH_SMI_STS_PERIODIC |
+ B_PCH_SMI_STS_TCO |
+ B_PCH_SMI_STS_MCSMI |
+ B_PCH_SMI_STS_SWSMI_TMR |
+ B_PCH_SMI_STS_APM |
+ B_PCH_SMI_STS_ON_SLP_EN |
+ B_PCH_SMI_STS_BIOS
+ );
+ DevActSts |=
+ (
+ B_PCH_DEVACT_STS_KBC |
+ B_PCH_DEVACT_STS_PIRQDH |
+ B_PCH_DEVACT_STS_PIRQCG |
+ B_PCH_DEVACT_STS_PIRQBF |
+ B_PCH_DEVACT_STS_PIRQAE
+ );
+ Tco1Sts |=
+ (
+ B_PCH_TCO1_STS_DMISERR |
+ B_PCH_TCO1_STS_DMISMI |
+ B_PCH_TCO1_STS_DMISCI |
+ B_PCH_TCO1_STS_BIOSWR |
+ B_PCH_TCO1_STS_NEWCENTURY |
+ B_PCH_TCO1_STS_TIMEOUT |
+ B_PCH_TCO1_STS_TCO_INT |
+ B_PCH_TCO1_STS_SW_TCO_SMI
+ );
+
+ GpioClearAllGpiSmiSts ();
+
+ //
+ // If NewCentury Sts is set here, it must clear the NewCentury Sts separately.
+ //
+ PchTcoClearNewCenturySts (NULL);
+
+ IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS), Tco1Sts);
+
+ //
+ // We do not want to write 1 to clear INTRD_DET bit.
+ //
+ IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO2_STS), (UINT16) ~B_PCH_TCO2_STS_INTRD_DET);
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS), SmiSts);
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS), DevActSts);
+
+ ///
+ /// Try to clear the EOS bit. ASSERT on an error
+ ///
+ EosSet = PchSmmSetAndCheckEos ();
+ ASSERT (EosSet);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Reset the PCH to generate subsequent SMIs
+ ///
+ SmiEn |= B_PCH_SMI_EN_EOS;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
+
+ ///
+ /// Double check that the assert worked
+ ///
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Return TRUE if EOS is set correctly
+ ///
+ if ((SmiEn & B_PCH_SMI_EN_EOS) == 0) {
+ ///
+ /// EOS was not set to a 1; this is an error
+ ///
+ return FALSE;
+ } else {
+ ///
+ /// EOS was correctly set to a 1
+ ///
+ return TRUE;
+ }
+}
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ )
+{
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+
+ return SciEn;
+}
+
+/**
+ Read a specifying bit with the register
+ These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegSize;
+ BOOLEAN BitWasOne;
+ UINTN ShiftCount;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+ UINTN PciBaseAddress;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+ ShiftCount = 0;
+ BitWasOne = FALSE;
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case TCO_ADDR_TYPE:
+ if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.tco;
+ BaseAddr = mTcoBaseAddr;
+ }
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// Double check that we correctly read in the acpi base address
+ ///
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ ShiftCount = BitDesc->Bit;
+ ///
+ /// As current CPU Smm Io can only support at most
+ /// 32-bit read/write,if Operation is 64 bit,
+ /// we do a 32 bit operation according to BitDesc->Bit
+ ///
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ ///
+ /// If the operation is for high 32 bits
+ ///
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+ ShiftCount -= 32;
+ }
+ }
+
+ Status = gSmst->SmmIo.Io.Read (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case GPIO_ADDR_TYPE:
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ ///
+ /// Read the register, and it with the bit to read
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ Register = (UINT64) MmioRead8 (PciBaseAddress + PciReg);
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 (PciBaseAddress + PciReg);
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 (PciBaseAddress + PciReg);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCR_ADDR_TYPE:
+ ///
+ /// Read the register, and it with the bit to read
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ PchPcrRead8 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8*) &Register);
+ break;
+
+ case 2:
+ PchPcrRead16 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16*) &Register);
+ break;
+
+ case 4:
+ PchPcrRead32 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32*) &Register);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ default:
+ ///
+ /// This address type is not yet implemented
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ return BitWasOne;
+}
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite,
+ CONST BOOLEAN WriteClear
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT64 AndVal;
+ UINT64 OrVal;
+ UINT32 RegSize;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+ UINTN PciBaseAddress;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
+ }
+
+ OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case TCO_ADDR_TYPE:
+ if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.tco;
+ BaseAddr = mTcoBaseAddr;
+ }
+
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// Double check that we correctly read in the acpi base address
+ ///
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ ///
+ /// As current CPU Smm Io can only support at most
+ /// 32-bit read/write,if Operation is 64 bit,
+ /// we do a 32 bit operation according to BitDesc->Bit
+ ///
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ ///
+ /// If the operation is for high 32 bits
+ ///
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
+ }
+
+ OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
+ }
+ }
+
+ Status = gSmst->SmmIo.Io.Read (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Register &= AndVal;
+ Register |= OrVal;
+
+ Status = gSmst->SmmIo.Io.Write (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case GPIO_ADDR_TYPE:
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ ///
+ /// Read the register, or it with the bit to set, then write it back.
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ MmioAndThenOr8 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ MmioAndThenOr16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ MmioAndThenOr32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ Register &= AndVal;
+ Register |= OrVal;
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized -- check your assignments
+ /// to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ MmioAndThenOr8 (PciBaseAddress + PciReg, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ MmioAndThenOr16 (PciBaseAddress + PciReg, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ MmioAndThenOr32 (PciBaseAddress + PciReg, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case PCR_ADDR_TYPE:
+ ///
+ /// Read the register, or it with the bit to set, then write it back.
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ PchPcrAndThenOr8 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ PchPcrAndThenOr16 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ PchPcrAndThenOr32 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ default:
+ ///
+ /// This address type is not yet implemented
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
new file mode 100644
index 0000000000..273bed32bc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
@@ -0,0 +1,114 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCHX_SMM_HELPERS_H_
+#define _PCHX_SMM_HELPERS_H_
+
+#include "PchSmm.h"
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ );
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ );
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ );
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ );
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ );
+
+/**
+ Read a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc
+ );
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite,
+ CONST BOOLEAN WriteClear
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
new file mode 100644
index 0000000000..2871b6c7c4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
@@ -0,0 +1,61 @@
+## @file
+# Component description file for SmmControl module
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SmmControl
+FILE_GUID = A0BAD9F7-AB78-491b-B583-C52B7F84B9E0
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_RUNTIME_DRIVER
+ENTRY_POINT = SmmControlDriverEntryInit
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+
+[LibraryClasses]
+IoLib
+UefiDriverEntryPoint
+DebugLib
+UefiBootServicesTableLib
+UefiRuntimeServicesTableLib
+PchCycleDecodingLib
+GpioLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SmmControlDriver.h
+SmmControlDriver.c
+
+
+[Protocols]
+gEfiSmmControl2ProtocolGuid ## PRODUCES
+
+
+[Guids]
+gEfiEventVirtualAddressChangeGuid
+
+
+[Depex]
+TRUE
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
new file mode 100644
index 0000000000..96727dde8f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
@@ -0,0 +1,400 @@
+/** @file
+ This is the driver that publishes the SMM Control Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "SmmControlDriver.h"
+
+STATIC SMM_CONTROL_PRIVATE_DATA mSmmControl;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mABase;
+
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ );
+
+/**
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+ @param[in] Event The event registered.
+ @param[in] Context Event context.
+
+**/
+VOID
+EFIAPI
+SmmControlVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl.SmmControl.Trigger));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl.SmmControl.Clear));
+}
+
+/**
+ <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SmmControl module is a DXE RUNTIME driver that provides a standard way
+ for other drivers to trigger software SMIs.
+
+ - @pre
+ - PCH Power Management I/O space base address has already been programmed.
+ If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+ is installed and there is the need to use Status code in the driver, it will
+ be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification.
+
+ - @result
+ The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+ System Management Mode Core Interface Specification.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_STATUS Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() Start\n"));
+
+ ///
+ /// Get the Power Management I/O space base address. We assume that
+ /// this base address has already been programmed if this driver is
+ /// being run.
+ ///
+ PchAcpiBaseGet (&mABase);
+
+ Status = EFI_SUCCESS;
+ if (mABase != 0) {
+ ///
+ /// Install the instance of the protocol
+ ///
+ mSmmControl.Signature = SMM_CONTROL_PRIVATE_DATA_SIGNATURE;
+ mSmmControl.Handle = ImageHandle;
+
+ mSmmControl.SmmControl.Trigger = Activate;
+ mSmmControl.SmmControl.Clear = Deactivate;
+ mSmmControl.SmmControl.MinimumTriggerPeriod = 0;
+
+ ///
+ /// Install our protocol interfaces on the device's handle
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mSmmControl.Handle,
+ &gEfiSmmControl2ProtocolGuid,
+ &mSmmControl.SmmControl,
+ NULL
+ );
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ SmmControlVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ///
+ /// Disable any PCH SMIs that, for whatever reason, are asserted after the boot.
+ ///
+ DisablePendingSmis ();
+
+ DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() End\n"));
+
+ return Status;
+}
+
+/**
+ Trigger the software SMI
+
+ @param[in] Data The value to be set on the software SMI data port
+
+ @retval EFI_SUCCESS Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+ IN UINT8 Data
+ )
+{
+ UINT32 OutputData;
+ UINT32 OutputPort;
+
+ ///
+ /// Enable the APMC SMI
+ ///
+ OutputPort = mABase + R_PCH_SMI_EN;
+ OutputData = IoRead32 ((UINTN) OutputPort);
+ OutputData |= (B_PCH_SMI_EN_APMC | B_PCH_SMI_EN_GBL_SMI);
+ DEBUG (
+ (DEBUG_EVENT,
+ "The SMI Control Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ OutputPort = R_PCH_APM_CNT;
+ OutputData = Data;
+
+ ///
+ /// Generate the APMC SMI
+ ///
+ IoWrite8 (
+ (UINTN) OutputPort,
+ (UINT8) (OutputData)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear the SMI status
+
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_DEVICE_ERROR Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 OutputData;
+ UINT32 OutputPort;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Clear the Power Button Override Status Bit, it gates EOS from being set.
+ ///
+ OutputPort = mABase + R_PCH_ACPI_PM1_STS;
+ OutputData = B_PCH_ACPI_PM1_STS_PRBTNOR;
+ DEBUG (
+ (DEBUG_EVENT,
+ "The PM1 Status Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite16 (
+ (UINTN) OutputPort,
+ (UINT16) (OutputData)
+ );
+
+ ///
+ /// Clear the APM SMI Status Bit
+ ///
+ OutputPort = mABase + R_PCH_SMI_STS;
+ OutputData = B_PCH_SMI_STS_APM;
+ DEBUG (
+ (DEBUG_EVENT,
+ "The SMI Status Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ ///
+ /// Set the EOS Bit
+ ///
+ OutputPort = mABase + R_PCH_SMI_EN;
+ OutputData = IoRead32 ((UINTN) OutputPort);
+ OutputData |= B_PCH_SMI_EN_EOS;
+ DEBUG (
+ (DEBUG_EVENT,
+ "The SMI Control Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ ///
+ /// There is no need to read EOS back and check if it is set.
+ /// This can lead to a reading of zero if an SMI occurs right after the SMI_EN port read
+ /// but before the data is returned to the CPU.
+ /// SMM Dispatcher should make sure that EOS is set after all SMI sources are processed.
+ ///
+ return Status;
+}
+
+/**
+ This routine generates an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in, out] CommandPort The buffer contains data to the command port
+ @param[in, out] DataPort The buffer contains data to the data port
+ @param[in] Periodic Periodic or not
+ @param[in] ActivationInterval Interval of periodic SMI
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL * This,
+ IN OUT UINT8 *CommandPort OPTIONAL,
+ IN OUT UINT8 *DataPort OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+
+ if (Periodic) {
+ DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CommandPort == NULL) {
+ Data = 0xFF;
+ } else {
+ Data = *CommandPort;
+ }
+ ///
+ /// Clear any pending the APM SMI
+ ///
+ Status = SmmClear ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return SmmTrigger (Data);
+}
+
+/**
+ This routine clears an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in] Periodic Periodic or not
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ )
+{
+ if (Periodic) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return SmmClear ();
+}
+/**
+ Disable all pending SMIs
+
+
+**/
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ )
+{
+ UINT32 Data;
+ UINT32 Port;
+ BOOLEAN SciEn;
+
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Port = mABase + R_PCH_ACPI_PM1_CNT;
+ Data = IoRead16 ((UINTN) Port);
+ SciEn = (BOOLEAN) ((Data & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+
+ if (!SciEn) {
+ ///
+ /// Clear any SMIs that double as SCIs (when SCI_EN==0)
+ ///
+ Port = mABase + R_PCH_ACPI_PM1_STS;
+ Data = 0xFFFF;
+ IoWrite16 ((UINTN) Port, (UINT16) (Data));
+
+ Port = mABase + R_PCH_ACPI_PM1_EN;
+ Data = 0x0000;
+ IoWrite16 ((UINTN) Port, (UINT16) (Data));
+
+ Port = mABase + R_PCH_ACPI_PM1_CNT;
+ Data = 0x0000;
+ IoWrite16 ((UINTN) Port, (UINT16) (Data));
+ Port = mABase + R_PCH_ACPI_GPE0_STS_127_96;
+ Data = (UINT32) ~B_PCH_ACPI_GPE0_STS_127_96_WADT;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+
+ Port = mABase + R_PCH_ACPI_GPE0_EN_127_96;
+ Data = B_PCH_ACPI_GPE0_EN_127_96_WADT;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+ }
+ ///
+ /// Clear and disable all SMIs that are unaffected by SCI_EN
+ ///
+ GpioDisableAllGpiSmi ();
+
+ GpioClearAllGpiSmiSts ();
+
+ Port = mABase + R_PCH_DEVACT_STS;
+ Data = 0xFFFF;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+
+ Port = mABase + R_PCH_SMI_STS;
+ Data = 0xFFFFFFFF;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+
+ ///
+ /// (Make sure to write this register last -- EOS re-enables SMIs for the PCH)
+ ///
+ Port = mABase + R_PCH_SMI_EN;
+ Data = IoRead32 ((UINTN) Port);
+ ///
+ /// clear all bits except those tied to SCI_EN
+ ///
+ Data &= B_PCH_SMI_EN_BIOS_RLS;
+ ///
+ /// enable SMIs and specifically enable writes to APM_CNT.
+ ///
+ Data |= B_PCH_SMI_EN_GBL_SMI | B_PCH_SMI_EN_APMC;
+ ///
+ /// NOTE: Default value of EOS is set in PCH, it will be automatically cleared Once the PCH asserts SMI# low,
+ /// we don't need to do anything to clear it
+ ///
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
new file mode 100644
index 0000000000..110b93a3ca
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
@@ -0,0 +1,148 @@
+/** @file
+ Header file for SMM Control Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SMM_CONTROL_DRIVER_H_
+#define _SMM_CONTROL_DRIVER_H_
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/EventGroup.h>
+#include <Protocol/SmmControl2.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioLib.h>
+#define EFI_INTERNAL_POINTER 0x00000004
+
+#define SMM_CONTROL_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', '4', 's', 'c')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_CONTROL2_PROTOCOL SmmControl;
+} SMM_CONTROL_PRIVATE_DATA;
+
+#define SMM_CONTROL_PRIVATE_DATA_FROM_THIS(a) CR (a, SMM_CONTROL_PRIVATE_DATA, SmmControl, SMM_CONTROL_DEV_SIGNATURE)
+
+//
+// Prototypes
+//
+
+/**
+ <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SmmControl module is a DXE RUNTIME driver that provides a standard way
+ for other drivers to trigger software SMIs.
+
+ - @pre
+ - PCH Power Management I/O space base address has already been programmed.
+ If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+ is installed and there is the need to use Status code in the driver, it will
+ be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification.
+
+ - @result
+ The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+ System Management Mode Core Interface Specification.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_STATUS Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Trigger the software SMI
+
+ @param[in] Data The value to be set on the software SMI data port
+
+ @retval EFI_SUCCESS Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+ UINT8 Data
+ );
+
+/**
+ Clear the SMI status
+
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_DEVICE_ERROR Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+ VOID
+ );
+
+/**
+ This routine generates an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in, out] ArgumentBuffer The buffer of argument
+ @param[in, out] ArgumentBufferSize The size of the argument buffer
+ @param[in] Periodic Periodic or not
+ @param[in] ActivationInterval Interval of periodic SMI
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN OUT UINT8 *ArgumentBuffer OPTIONAL,
+ IN OUT UINT8 *ArgumentBufferSize OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ );
+
+/**
+ This routine clears an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in] Periodic Periodic or not
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ );
+/**
+ Disable all pending SMIs
+
+**/
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c
new file mode 100644
index 0000000000..5cc808aa9d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c
@@ -0,0 +1,254 @@
+/** @file
+ PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PchSpi.h"
+
+//
+// Global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance;
+//
+// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.
+// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range
+// won't overlap with SMRAM range, and trusted.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr;
+
+/**
+ <b>SPI Runtime SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SPI SMM module provide a standard way for other modules to use the PCH SPI Interface in SMM.
+
+ - @pre
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in System Management Mode Core Interface Specification .
+
+ - @result
+ The SPI SMM driver produces @link _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL @endlink with GUID
+ gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.
+
+ - <b>Integration Check List</b>\n
+ - This driver supports Descriptor Mode only.
+ - This driver supports Hardware Sequence only.
+ - When using SMM SPI Protocol to perform flash access in an SMI handler,
+ and the SMI occurrence is asynchronous to normal mode code execution,
+ proper synchronization mechanism must be applied, e.g. disable SMI before
+ the normal mode SendSpiCmd() starts and re-enable SMI after
+ the normal mode SendSpiCmd() completes.
+ @note The implementation of SendSpiCmd() uses GBL_SMI_EN in
+ SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may
+ not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI Offset A0h [4]).
+ So the synchronization at caller level is likely needed.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init PCH spi reserved MMIO address.
+ //
+ mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
+
+ ///
+ /// Allocate pool for SPI protocol instance
+ ///
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData, /// MemoryType don't care
+ sizeof (SPI_INSTANCE),
+ (VOID **) &mSpiInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+ ///
+ /// Initialize the SPI protocol instance
+ ///
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Install the SMM PCH_SPI_PROTOCOL interface
+ ///
+ Status = gSmst->SmmInstallProtocolInterface (
+ &(mSpiInstance->Handle),
+ &gPchSmmSpiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(mSpiInstance->SpiProtocol)
+ );
+ if (EFI_ERROR (Status)) {
+ gSmst->SmmFreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Acquire PCH spi mmio address.
+ It is not expected for this BAR0 to change because the SPI device is hidden
+ from the OS for SKL PCH LP/H B stepping and above (refer to section 3.5.1),
+ but 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 = MmioRead32 (SpiInstance->PchSpiBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+
+ if (SpiBar0 != mSpiResvMmioAddr) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ MmioAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (SpiInstance->PchSpiBase + R_PCH_SPI_BAR0, mSpiResvMmioAddr);
+ MmioOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+ //
+ // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg.
+ //
+ return mSpiResvMmioAddr;
+}
+
+/**
+ Release pch spi mmio address. Do nothing.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+
+ SpiBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.
+ //
+ MmioOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC + 1,
+ (B_PCH_SPI_BC_SYNC_SS >> 8)
+ );
+ ///
+ /// Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ /// Enable the access to the BIOS space for both read and write cycles
+ ///
+ MmioOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ B_PCH_SPI_BC_WPD
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling
+ /// If the following steps are implemented:
+ /// - Set the EISS bit (SPI PCI Offset DCh [5]) = 1b
+ /// - Follow the 1st recommendation in section 3.6
+ /// the BIOS Region can only be updated by following the steps bellow:
+ /// - Once all threads enter SMM
+ /// - Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ /// - Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ /// - Modify BIOS Region
+ /// - Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ ///
+ if ((MmioRead8 (SpiBaseAddress + R_PCH_SPI_BC) & B_PCH_SPI_BC_EISS) != 0) {
+ CpuSmmDisableBiosWriteProtect ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+
+ SpiBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ ///
+ /// Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ /// Disable the access to the BIOS space for write cycles
+ ///
+ MmioAnd8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) (~B_PCH_SPI_BC_WPD)
+ );
+
+ ///
+ /// Check if EISS bit is set
+ ///
+ if (((MmioRead8 (SpiBaseAddress + R_PCH_SPI_BC)) & B_PCH_SPI_BC_EISS) == B_PCH_SPI_BC_EISS) {
+ CpuSmmEnableBiosWriteProtect ();
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h
new file mode 100644
index 0000000000..e3b6d7fd90
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h
@@ -0,0 +1,30 @@
+/** @file
+ Header file for the PCH SPI SMM Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Protocol/Spi.h>
+#include <Library/PchSpiCommonLib.h>
+#include <Library/CpuCommonLib.h>
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
new file mode 100644
index 0000000000..52f83a9953
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
@@ -0,0 +1,54 @@
+## @file
+# Component description file for the SPI SMM driver.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchSpiSmm
+FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InstallPchSpi
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+UefiDriverEntryPoint
+UefiBootServicesTableLib
+BaseLib
+SmmServicesTableLib
+PchSpiCommonLib
+CpuCommonLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+PchSpi.h
+PchSpi.c
+
+
+[Protocols]
+gPchSmmSpiProtocolGuid ## PRODUCES
+
+
+[Depex]
+gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib
+gEfiSmmCpuProtocolGuid # This is for CpuSmmDisableBiosWriteProtect()
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/Include/Library/SecPlatformLib.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/Include/Library/SecPlatformLib.h
new file mode 100644
index 0000000000..f9bbc931aa
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/Include/Library/SecPlatformLib.h
@@ -0,0 +1,88 @@
+/** @file
+ Prototype of SEC Platform hook library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SEC_PLATFORM_LIB_H_
+#define _SEC_PLATFORM_LIB_H_
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/SecPerformance.h>
+
+/**
+ A developer supplied function to perform platform specific operations.
+
+ It's a developer supplied function to perform any operations appropriate to a
+ given platform. It's invoked just before passing control to PEI core by SEC
+ core. Platform developer may modify the SecCoreData passed to PEI Core.
+ It returns a platform specific PPI list that platform wishes to pass to PEI core.
+ The Generic SEC core module will merge this list to join the final list passed to
+ PEI core.
+
+ @param SecCoreData The same parameter as passing to PEI core. It
+ could be overridden by this function.
+
+ @return The platform specific PPI list to be passed to PEI core or
+ NULL if there is no need of such platform specific PPI list.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+ IN OUT EFI_SEC_PEI_HAND_OFF *SecCoreData
+ );
+
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param StructureSize Pointer to the variable describing size of the input buffer.
+ @param PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_BUFFER_TOO_SMALL The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ );
+
+/**
+ This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+ This service is published by the SEC phase. The SEC phase handoff has an optional
+ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+ PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+ this information is encapsulated into the data structure abstracted by this service.
+ This information is collected for the boot-strap processor (BSP) on IA-32.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+ @param[out] Performance The pointer to performance data collected in SEC phase.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+**/
+EFI_STATUS
+EFIAPI
+SecGetPerformance (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SEC_PERFORMANCE_PPI *This,
+ OUT FIRMWARE_SEC_PERFORMANCE *Performance
+ );
+
+#endif
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h
new file mode 100644
index 0000000000..d18a2eda21
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkModulePkg/Include/Guid/DataHubStatusCodeRecord.h
@@ -0,0 +1,61 @@
+/** @file
+ GUID used to identify Data Hub records logged by Status Code Protocol.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __DATA_HUB_STATUS_CODE_RECORD_H__
+#define __DATA_HUB_STATUS_CODE_RECORD_H__
+
+///
+/// The Global ID used to identify a structure of type DATA_HUB_STATUS_CODE_DATA_RECORD.
+///
+#define EFI_DATA_HUB_STATUS_CODE_RECORD_GUID \
+ { \
+ 0xd083e94c, 0x6560, 0x42e4, {0xb6, 0xd4, 0x2d, 0xf7, 0x5a, 0xdf, 0x6a, 0x2a } \
+ }
+
+///
+/// The Data Hub data record that is used to store all the parameters passed into
+/// the ReportStatusCode() service of the EFI_STATUS_CODE_PROTOCOL.
+///
+typedef struct {
+ ///
+ /// Status Code type to be reported.
+ ///
+ EFI_STATUS_CODE_TYPE CodeType;
+
+ ///
+ /// An operation, plus value information about the class and subclass, used to
+ /// classify the hardware and software entity.
+ ///
+ EFI_STATUS_CODE_VALUE Value;
+
+ ///
+ /// The enumeration of a hardware or software entity within
+ /// the system. Valid instance numbers start with 1.
+ ///
+ UINT32 Instance;
+
+ ///
+ /// Identify the caller.
+ ///
+ EFI_GUID CallerId;
+
+ ///
+ /// Additional status code data.
+ ///
+ EFI_STATUS_CODE_DATA Data;
+} DATA_HUB_STATUS_CODE_DATA_RECORD;
+
+extern EFI_GUID gEfiDataHubStatusCodeRecordGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Guid/SmramMemoryReserve.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Guid/SmramMemoryReserve.h
new file mode 100644
index 0000000000..04589cf040
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Guid/SmramMemoryReserve.h
@@ -0,0 +1,60 @@
+/** @file
+ Definition of GUIDed HOB for reserving SMRAM regions.
+
+ This file defines:
+ * the GUID used to identify the GUID HOB for reserving SMRAM regions.
+ * the data structure of SMRAM descriptor to describe SMRAM candidate regions
+ * values of state of SMRAM candidate regions
+ * the GUID specific data structure of HOB for reserving SMRAM regions.
+ This GUIDed HOB can be used to convey the existence of the T-SEG reservation and H-SEG usage
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ GUIDs defined in SmmCis spec version 0.9.
+
+**/
+
+#ifndef _EFI_SMM_PEI_SMRAM_MEMORY_RESERVE_H_
+#define _EFI_SMM_PEI_SMRAM_MEMORY_RESERVE_H_
+
+#define EFI_SMM_PEI_SMRAM_MEMORY_RESERVE \
+ { \
+ 0x6dadf1d1, 0xd4cc, 0x4910, {0xbb, 0x6e, 0x82, 0xb1, 0xfd, 0x80, 0xff, 0x3d } \
+ }
+
+/**
+* GUID specific data structure of HOB for reserving SMRAM regions.
+*
+* Inconsistent with specification here:
+* EFI_HOB_SMRAM_DESCRIPTOR_BLOCK has been changed to EFI_SMRAM_HOB_DESCRIPTOR_BLOCK.
+* This inconsistency is kept in code in order for backward compatibility.
+**/
+typedef struct {
+ ///
+ /// Designates the number of possible regions in the system
+ /// that can be usable for SMRAM.
+ ///
+ /// Inconsistent with specification here:
+ /// In Framework SMM CIS 0.91 specification, it defines the field type as UINTN.
+ /// However, HOBs are supposed to be CPU neutral, so UINT32 should be used instead.
+ ///
+ UINT32 NumberOfSmmReservedRegions;
+ ///
+ /// Used throughout this protocol to describe the candidate
+ /// regions for SMRAM that are supported by this platform.
+ ///
+ EFI_SMRAM_DESCRIPTOR Descriptor[1];
+} EFI_SMRAM_HOB_DESCRIPTOR_BLOCK;
+
+extern EFI_GUID gEfiSmmPeiSmramMemoryReserveGuid;
+
+#endif
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/DataHub.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/DataHub.h
new file mode 100644
index 0000000000..ce73e3e8a6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/DataHub.h
@@ -0,0 +1,222 @@
+/** @file
+ The data hub protocol is used both by agents wishing to log
+ data and those wishing to be made aware of all information that
+ has been logged. This protocol may only be called <= TPL_NOTIFY.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ The Data Hub Protocol is defined in Framework for EFI Data Hub Specification
+ Version 0.9.
+
+**/
+
+#ifndef __DATA_HUB_H__
+#define __DATA_HUB_H__
+
+#define EFI_DATA_HUB_PROTOCOL_GUID \
+ { \
+ 0xae80d021, 0x618e, 0x11d4, {0xbc, 0xd7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
+ }
+
+//
+// EFI generic Data Hub Header
+//
+// A Data Record is an EFI_DATA_RECORD_HEADER followed by RecordSize bytes of
+// data. The format of the data is defined by the DataRecordGuid.
+//
+// If EFI_DATA_RECORD_HEADER is extended in the future, the Version number and HeaderSize must
+// change.
+//
+// The logger is responcible for initializing:
+// Version, HeaderSize, RecordSize, DataRecordGuid, DataRecordClass
+//
+// The Data Hub driver is responcible for initializing:
+// LogTime and LogMonotonicCount.
+//
+#define EFI_DATA_RECORD_HEADER_VERSION 0x0100
+typedef struct {
+ UINT16 Version;
+ UINT16 HeaderSize;
+ UINT32 RecordSize;
+ EFI_GUID DataRecordGuid;
+ EFI_GUID ProducerName;
+ UINT64 DataRecordClass;
+ EFI_TIME LogTime;
+ UINT64 LogMonotonicCount;
+} EFI_DATA_RECORD_HEADER;
+
+//
+// Definition of DataRecordClass. These are used to filter out class types
+// at a very high level. The DataRecordGuid still defines the format of
+// the data. See the Data Hub Specification for rules on what can and can not be a
+// new DataRecordClass
+//
+#define EFI_DATA_RECORD_CLASS_DEBUG 0x0000000000000001
+#define EFI_DATA_RECORD_CLASS_ERROR 0x0000000000000002
+#define EFI_DATA_RECORD_CLASS_DATA 0x0000000000000004
+#define EFI_DATA_RECORD_CLASS_PROGRESS_CODE 0x0000000000000008
+
+//
+// Forward reference for pure ANSI compatability
+//
+typedef struct _EFI_DATA_HUB_PROTOCOL EFI_DATA_HUB_PROTOCOL;
+
+/**
+ Logs a data record to the system event log.
+
+ @param This The EFI_DATA_HUB_PROTOCOL instance.
+ @param DataRecordGuid A GUID that indicates the format of the data passed into RawData.
+ @param ProducerName A GUID that indicates the identity of the caller to this API.
+ @param DataRecordClass This class indicates the generic type of the data record.
+ @param RawData The DataRecordGuid-defined data to be logged.
+ @param RawDataSize The size in bytes of RawData.
+
+ @retval EFI_SUCCESS Data was logged.
+ @retval EFI_OUT_OF_RESOURCES Data was not logged due to lack of system resources.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DATA_HUB_LOG_DATA)(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_GUID *DataRecordGuid,
+ IN EFI_GUID *ProducerName,
+ IN UINT64 DataRecordClass,
+ IN VOID *RawData,
+ IN UINT32 RawDataSize
+ );
+
+/**
+ Allows the system data log to be searched.
+
+ @param This The EFI_DATA_HUB_PROTOCOL instance.
+ @param MonotonicCount On input, it specifies the Record to return.
+ An input of zero means to return the first record,
+ as does an input of one.
+ @param FilterDriver If FilterDriver is not passed in a MonotonicCount
+ of zero, it means to return the first data record.
+ If FilterDriver is passed in, then a MonotonicCount
+ of zero means to return the first data not yet read
+ by FilterDriver.
+ @param Record Returns a dynamically allocated memory buffer with
+ a data record that matches MonotonicCount.
+
+ @retval EFI_SUCCESS Data was returned in Record.
+ @retval EFI_INVALID_PARAMETER FilterDriver was passed in but does not exist.
+ @retval EFI_NOT_FOUND MonotonicCount does not match any data record
+ in the system. If a MonotonicCount of zero was
+ passed in, then no data records exist in the system.
+ @retval EFI_OUT_OF_RESOURCES Record was not returned due to lack
+ of system resources.
+ @note Inconsistent with specification here:
+ In Framework for EFI Data Hub Specification, Version 0.9, This definition
+ is named as EFI_DATA_HUB_GET_NEXT_DATA_RECORD. The inconsistency is
+ maintained for backward compatibility.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DATA_HUB_GET_NEXT_RECORD)(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN OUT UINT64 *MonotonicCount,
+ IN EFI_EVENT *FilterDriver OPTIONAL,
+ OUT EFI_DATA_RECORD_HEADER **Record
+ );
+
+/**
+ Registers an event to be signaled every time a data record is logged in the system.
+
+ @param This The EFI_DATA_HUB_PROTOCOL instance.
+ @param FilterEvent The EFI_EVENT to signal whenever data that matches
+ FilterClass is logged in the system.
+ @param FilterTpl The maximum EFI_TPL at which FilterEvent can be
+ signaled. It is strongly recommended that you use
+ the lowest EFI_TPL possible.
+ @param FilterClass FilterEvent will be signaled whenever a bit
+ in EFI_DATA_RECORD_HEADER.DataRecordClass is also
+ set in FilterClass. If FilterClass is zero, no
+ class-based filtering will be performed.
+ @param FilterDataRecordGuid FilterEvent will be signaled whenever
+ FilterDataRecordGuid matches
+ EFI_DATA_RECORD_HEADER.DataRecordGuid.
+ If FilterDataRecordGuid is NULL, then no GUID-based
+ filtering will be performed.
+
+ @retval EFI_SUCCESS The filter driver event was registered
+ @retval EFI_ALREADY_STARTED FilterEvent was previously registered and cannot
+ be registered again.
+ @retval EFI_OUT_OF_RESOURCES The filter driver event was not registered
+ due to lack of system resources.
+ @note Inconsistent with specification here:
+ In Framework for EFI Data Hub Specification, Version 0.9, This definition
+ is named as EFI_DATA_HUB_REGISTER_DATA_FILTER_DRIVER. The inconsistency
+ is maintained for backward compatibility.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DATA_HUB_REGISTER_FILTER_DRIVER)(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_EVENT FilterEvent,
+ IN EFI_TPL FilterTpl,
+ IN UINT64 FilterClass,
+ IN EFI_GUID *FilterDataRecordGuid OPTIONAL
+ );
+
+/**
+ Stops a filter driver from being notified when data records are logged.
+
+ @param This The EFI_DATA_HUB_PROTOCOL instance.
+ @param FilterEvent The EFI_EVENT to remove from the list of events to be
+ signaled every time errors are logged.
+
+ @retval EFI_SUCCESS The filter driver represented by FilterEvent was shut off.
+ @retval EFI_NOT_FOUND FilterEvent did not exist.
+ @note Inconsistent with specification here:
+ In Framework for EFI Data Hub Specification, Version 0.9, This definition
+ is named as EFI_DATA_HUB_UNREGISTER_DATA_FILTER_DRIVER. The inconsistency
+ is maintained for backward compatibility.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DATA_HUB_UNREGISTER_FILTER_DRIVER)(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_EVENT FilterEvent
+ );
+
+/**
+ This protocol is used to log information and register filter drivers
+ to receive data records.
+**/
+struct _EFI_DATA_HUB_PROTOCOL {
+ ///
+ /// Logs a data record.
+ ///
+ EFI_DATA_HUB_LOG_DATA LogData;
+
+ ///
+ /// Gets a data record. Used both to view the memory-based log and to
+ /// get information about which data records have been consumed by a filter driver.
+ ///
+ EFI_DATA_HUB_GET_NEXT_RECORD GetNextRecord;
+
+ ///
+ /// Allows the registration of an EFI event to act as a filter driver for all data records that are logged.
+ ///
+ EFI_DATA_HUB_REGISTER_FILTER_DRIVER RegisterFilterDriver;
+
+ ///
+ /// Used to remove a filter driver that was added with RegisterFilterDriver().
+ ///
+ EFI_DATA_HUB_UNREGISTER_FILTER_DRIVER UnregisterFilterDriver;
+};
+
+extern EFI_GUID gEfiDataHubProtocolGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/Legacy8259.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/Legacy8259.h
new file mode 100644
index 0000000000..c12936f2d2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/Legacy8259.h
@@ -0,0 +1,297 @@
+/** @file
+ This protocol abstracts the 8259 interrupt controller. This includes
+ PCI IRQ routing needed to program the PCI Interrupt Line register.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This protocol is defined in Framework for EFI Compatibility Support Module spec
+ Version 0.97.
+
+**/
+
+#ifndef _EFI_LEGACY_8259_H_
+#define _EFI_LEGACY_8259_H_
+
+
+#define EFI_LEGACY_8259_PROTOCOL_GUID \
+ { \
+ 0x38321dba, 0x4fe0, 0x4e17, {0x8a, 0xec, 0x41, 0x30, 0x55, 0xea, 0xed, 0xc1 } \
+ }
+
+typedef struct _EFI_LEGACY_8259_PROTOCOL EFI_LEGACY_8259_PROTOCOL;
+
+typedef enum {
+ Efi8259Irq0,
+ Efi8259Irq1,
+ Efi8259Irq2,
+ Efi8259Irq3,
+ Efi8259Irq4,
+ Efi8259Irq5,
+ Efi8259Irq6,
+ Efi8259Irq7,
+ Efi8259Irq8,
+ Efi8259Irq9,
+ Efi8259Irq10,
+ Efi8259Irq11,
+ Efi8259Irq12,
+ Efi8259Irq13,
+ Efi8259Irq14,
+ Efi8259Irq15,
+ Efi8259IrqMax
+} EFI_8259_IRQ;
+
+typedef enum {
+ Efi8259LegacyMode,
+ Efi8259ProtectedMode,
+ Efi8259MaxMode
+} EFI_8259_MODE;
+
+/**
+ Get the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for
+ the legacy mode mask and the protected mode mask. The base address for the 8259
+ is different for legacy and protected mode, so two masks are required.
+
+ @param This The protocol instance pointer.
+ @param MasterBase The base vector for the Master PIC in the 8259 controller.
+ @param SlaveBase The base vector for the Slave PIC in the 8259 controller.
+
+ @retval EFI_SUCCESS The new bases were programmed.
+ @retval EFI_DEVICE_ERROR A device error occured programming the vector bases.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_SET_VECTOR_BASE)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN UINT8 MasterBase,
+ IN UINT8 SlaveBase
+ );
+
+/**
+ Get the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for
+ the legacy mode mask and the protected mode mask. The base address for the 8259
+ is different for legacy and protected mode, so two masks are required.
+
+ @param This The protocol instance pointer.
+ @param LegacyMask Bit 0 is Irq0 - Bit 15 is Irq15.
+ @param LegacyEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15.
+ @param ProtectedMask Bit 0 is Irq0 - Bit 15 is Irq15.
+ @param ProtectedEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15.
+
+ @retval EFI_SUCCESS 8259 status returned.
+ @retval EFI_DEVICE_ERROR Error reading 8259.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_GET_MASK)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ OUT UINT16 *LegacyMask, OPTIONAL
+ OUT UINT16 *LegacyEdgeLevel, OPTIONAL
+ OUT UINT16 *ProtectedMask, OPTIONAL
+ OUT UINT16 *ProtectedEdgeLevel OPTIONAL
+ );
+
+/**
+ Set the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for
+ the legacy mode mask and the protected mode mask. The base address for the 8259
+ is different for legacy and protected mode, so two masks are required.
+ Also set the edge/level masks.
+
+ @param This The protocol instance pointer.
+ @param LegacyMask Bit 0 is Irq0 - Bit 15 is Irq15.
+ @param LegacyEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15.
+ @param ProtectedMask Bit 0 is Irq0 - Bit 15 is Irq15.
+ @param ProtectedEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15.
+
+ @retval EFI_SUCCESS 8259 status returned.
+ @retval EFI_DEVICE_ERROR Error writing 8259.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_SET_MASK)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN UINT16 *LegacyMask, OPTIONAL
+ IN UINT16 *LegacyEdgeLevel, OPTIONAL
+ IN UINT16 *ProtectedMask, OPTIONAL
+ IN UINT16 *ProtectedEdgeLevel OPTIONAL
+ );
+
+/**
+ Set the 8259 mode of operation. The base address for the 8259 is different for
+ legacy and protected mode. The legacy mode requires the master 8259 to have a
+ master base of 0x08 and the slave base of 0x70. The protected mode base locations
+ are not defined. Interrupts must be masked by the caller before this function
+ is called. The interrupt mask from the current mode is saved. The interrupt
+ mask for the new mode is Mask, or if Mask does not exist the previously saved
+ mask is used.
+
+ @param This The protocol instance pointer.
+ @param Mode The mode of operation. i.e. the real mode or protected mode.
+ @param Mask Optional interupt mask for the new mode.
+ @param EdgeLevel Optional trigger mask for the new mode.
+
+ @retval EFI_SUCCESS 8259 programmed.
+ @retval EFI_DEVICE_ERROR Error writing to 8259.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_SET_MODE)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN EFI_8259_MODE Mode,
+ IN UINT16 *Mask, OPTIONAL
+ IN UINT16 *EdgeLevel OPTIONAL
+ );
+
+/**
+ Convert from IRQ to processor interrupt vector number.
+
+ @param This The protocol instance pointer.
+ @param Irq 8259 IRQ0 - IRQ15.
+ @param Vector The processor vector number that matches an Irq.
+
+ @retval EFI_SUCCESS The Vector matching Irq is returned.
+ @retval EFI_INVALID_PARAMETER The Irq not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_GET_VECTOR)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN EFI_8259_IRQ Irq,
+ OUT UINT8 *Vector
+ );
+
+/**
+ Enable Irq by unmasking interrupt in 8259
+
+ @param This The protocol instance pointer.
+ @param Irq 8259 IRQ0 - IRQ15.
+ @param LevelTriggered TRUE if level triggered. FALSE if edge triggered.
+
+ @retval EFI_SUCCESS The Irq was enabled on 8259.
+ @retval EFI_INVALID_PARAMETER The Irq is not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_ENABLE_IRQ)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN EFI_8259_IRQ Irq,
+ IN BOOLEAN LevelTriggered
+ );
+
+/**
+ Disable Irq by masking interrupt in 8259
+
+ @param This The protocol instance pointer.
+ @param Irq 8259 IRQ0 - IRQ15.
+
+ @retval EFI_SUCCESS The Irq was disabled on 8259.
+ @retval EFI_INVALID_PARAMETER The Irq is not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_DISABLE_IRQ)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN EFI_8259_IRQ Irq
+ );
+
+/**
+ PciHandle represents a PCI config space of a PCI function. Vector
+ represents Interrupt Pin (from PCI config space) and it is the data
+ that is programmed into the Interrupt Line (from the PCI config space)
+ register.
+
+ @param This The protocol instance pointer.
+ @param PciHandle The PCI function to return the vector for.
+ @param Vector The vector for the function it matches.
+
+ @retval EFI_SUCCESS A valid Vector was returned.
+ @retval EFI_INVALID_PARAMETER PciHandle not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_GET_INTERRUPT_LINE)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN EFI_HANDLE PciHandle,
+ OUT UINT8 *Vector
+ );
+
+/**
+ Send an EOI to 8259
+
+ @param This The protocol instance pointer.
+ @param Irq 8259 IRQ0 - IRQ15.
+
+ @retval EFI_SUCCESS EOI was successfully sent to 8259.
+ @retval EFI_INVALID_PARAMETER The Irq isnot valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_8259_END_OF_INTERRUPT)(
+ IN EFI_LEGACY_8259_PROTOCOL *This,
+ IN EFI_8259_IRQ Irq
+ );
+
+/**
+ @par Protocol Description:
+ Abstracts the 8259 and APIC hardware control between EFI usage and
+ Compatibility16 usage.
+
+ @param SetVectorBase
+ Sets the vector bases for master and slave PICs.
+
+ @param GetMask
+ Gets IRQ and edge/level masks for 16-bit real mode and 32-bit protected mode.
+
+ @param SetMask
+ Sets the IRQ and edge\level masks for 16-bit real mode and 32-bit protected mode.
+
+ @param SetMode
+ Sets PIC mode to 16-bit real mode or 32-bit protected mode.
+
+ @param GetVector
+ Gets the base vector assigned to an IRQ.
+
+ @param EnableIrq
+ Enables an IRQ.
+
+ @param DisableIrq
+ Disables an IRQ.
+
+ @param GetInterruptLine
+ Gets an IRQ that is assigned to a PCI device.
+
+ @param EndOfInterrupt
+ Issues the end of interrupt command.
+
+**/
+struct _EFI_LEGACY_8259_PROTOCOL {
+ EFI_LEGACY_8259_SET_VECTOR_BASE SetVectorBase;
+ EFI_LEGACY_8259_GET_MASK GetMask;
+ EFI_LEGACY_8259_SET_MASK SetMask;
+ EFI_LEGACY_8259_SET_MODE SetMode;
+ EFI_LEGACY_8259_GET_VECTOR GetVector;
+ EFI_LEGACY_8259_ENABLE_IRQ EnableIrq;
+ EFI_LEGACY_8259_DISABLE_IRQ DisableIrq;
+ EFI_LEGACY_8259_GET_INTERRUPT_LINE GetInterruptLine;
+ EFI_LEGACY_8259_END_OF_INTERRUPT EndOfInterrupt;
+};
+
+extern EFI_GUID gEfiLegacy8259ProtocolGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyBios.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyBios.h
new file mode 100644
index 0000000000..a5f8f8abf7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyBios.h
@@ -0,0 +1,1523 @@
+/** @file
+ The EFI Legacy BIOS Protocol is used to abstract legacy Option ROM usage
+ under EFI and Legacy OS boot. This file also includes all the related
+ COMPATIBILIY16 structures and defintions.
+
+ Note: The names for EFI_IA32_REGISTER_SET elements were picked to follow
+ well known naming conventions.
+
+ Thunk is the code that switches from 32-bit protected environment into the 16-bit real-mode
+ environment. Reverse thunk is the code that does the opposite.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This protocol is defined in Framework for EFI Compatibility Support Module spec
+ Version 0.97.
+
+**/
+
+#ifndef _EFI_LEGACY_BIOS_H_
+#define _EFI_LEGACY_BIOS_H_
+
+///
+///
+///
+#pragma pack(1)
+
+typedef UINT8 SERIAL_MODE;
+typedef UINT8 PARALLEL_MODE;
+
+#define EFI_COMPATIBILITY16_TABLE_SIGNATURE SIGNATURE_32 ('I', 'F', 'E', '$')
+
+///
+/// There is a table located within the traditional BIOS in either the 0xF000:xxxx or 0xE000:xxxx
+/// physical address range. It is located on a 16-byte boundary and provides the physical address of the
+/// entry point for the Compatibility16 functions. These functions provide the platform-specific
+/// information that is required by the generic EfiCompatibility code. The functions are invoked via
+/// thunking by using EFI_LEGACY_BIOS_PROTOCOL.FarCall86() with the 32-bit physical
+/// entry point.
+///
+typedef struct {
+ ///
+ /// The string "$EFI" denotes the start of the EfiCompatibility table. Byte 0 is "I," byte
+ /// 1 is "F," byte 2 is "E," and byte 3 is "$" and is normally accessed as a DWORD or UINT32.
+ ///
+ UINT32 Signature;
+
+ ///
+ /// The value required such that byte checksum of TableLength equals zero.
+ ///
+ UINT8 TableChecksum;
+
+ ///
+ /// The length of this table.
+ ///
+ UINT8 TableLength;
+
+ ///
+ /// The major EFI revision for which this table was generated.
+ ///
+ UINT8 EfiMajorRevision;
+
+ ///
+ /// The minor EFI revision for which this table was generated.
+ ///
+ UINT8 EfiMinorRevision;
+
+ ///
+ /// The major revision of this table.
+ ///
+ UINT8 TableMajorRevision;
+
+ ///
+ /// The minor revision of this table.
+ ///
+ UINT8 TableMinorRevision;
+
+ ///
+ /// Reserved for future usage.
+ ///
+ UINT16 Reserved;
+
+ ///
+ /// The segment of the entry point within the traditional BIOS for Compatibility16 functions.
+ ///
+ UINT16 Compatibility16CallSegment;
+
+ ///
+ /// The offset of the entry point within the traditional BIOS for Compatibility16 functions.
+ ///
+ UINT16 Compatibility16CallOffset;
+
+ ///
+ /// The segment of the entry point within the traditional BIOS for EfiCompatibility
+ /// to invoke the PnP installation check.
+ ///
+ UINT16 PnPInstallationCheckSegment;
+
+ ///
+ /// The Offset of the entry point within the traditional BIOS for EfiCompatibility
+ /// to invoke the PnP installation check.
+ ///
+ UINT16 PnPInstallationCheckOffset;
+
+ ///
+ /// EFI system resources table. Type EFI_SYSTEM_TABLE is defined in the IntelPlatform
+ ///Innovation Framework for EFI Driver Execution Environment Core Interface Specification (DXE CIS).
+ ///
+ UINT32 EfiSystemTable;
+
+ ///
+ /// The address of an OEM-provided identifier string. The string is null terminated.
+ ///
+ UINT32 OemIdStringPointer;
+
+ ///
+ /// The 32-bit physical address where ACPI RSD PTR is stored within the traditional
+ /// BIOS. The remained of the ACPI tables are located at their EFI addresses. The size
+ /// reserved is the maximum for ACPI 2.0. The EfiCompatibility will fill in the ACPI
+ /// RSD PTR with either the ACPI 1.0b or 2.0 values.
+ ///
+ UINT32 AcpiRsdPtrPointer;
+
+ ///
+ /// The OEM revision number. Usage is undefined but provided for OEM module usage.
+ ///
+ UINT16 OemRevision;
+
+ ///
+ /// The 32-bit physical address where INT15 E820 data is stored within the traditional
+ /// BIOS. The EfiCompatibility code will fill in the E820Pointer value and copy the
+ /// data to the indicated area.
+ ///
+ UINT32 E820Pointer;
+
+ ///
+ /// The length of the E820 data and is filled in by the EfiCompatibility code.
+ ///
+ UINT32 E820Length;
+
+ ///
+ /// The 32-bit physical address where the $PIR table is stored in the traditional BIOS.
+ /// The EfiCompatibility code will fill in the IrqRoutingTablePointer value and
+ /// copy the data to the indicated area.
+ ///
+ UINT32 IrqRoutingTablePointer;
+
+ ///
+ /// The length of the $PIR table and is filled in by the EfiCompatibility code.
+ ///
+ UINT32 IrqRoutingTableLength;
+
+ ///
+ /// The 32-bit physical address where the MP table is stored in the traditional BIOS.
+ /// The EfiCompatibility code will fill in the MpTablePtr value and copy the data
+ /// to the indicated area.
+ ///
+ UINT32 MpTablePtr;
+
+ ///
+ /// The length of the MP table and is filled in by the EfiCompatibility code.
+ ///
+ UINT32 MpTableLength;
+
+ ///
+ /// The segment of the OEM-specific INT table/code.
+ ///
+ UINT16 OemIntSegment;
+
+ ///
+ /// The offset of the OEM-specific INT table/code.
+ ///
+ UINT16 OemIntOffset;
+
+ ///
+ /// The segment of the OEM-specific 32-bit table/code.
+ ///
+ UINT16 Oem32Segment;
+
+ ///
+ /// The offset of the OEM-specific 32-bit table/code.
+ ///
+ UINT16 Oem32Offset;
+
+ ///
+ /// The segment of the OEM-specific 16-bit table/code.
+ ///
+ UINT16 Oem16Segment;
+
+ ///
+ /// The offset of the OEM-specific 16-bit table/code.
+ ///
+ UINT16 Oem16Offset;
+
+ ///
+ /// The segment of the TPM binary passed to 16-bit CSM.
+ ///
+ UINT16 TpmSegment;
+
+ ///
+ /// The offset of the TPM binary passed to 16-bit CSM.
+ ///
+ UINT16 TpmOffset;
+
+ ///
+ /// A pointer to a string identifying the independent BIOS vendor.
+ ///
+ UINT32 IbvPointer;
+
+ ///
+ /// This field is NULL for all systems not supporting PCI Express. This field is the base
+ /// value of the start of the PCI Express memory-mapped configuration registers and
+ /// must be filled in prior to EfiCompatibility code issuing the Compatibility16 function
+ /// Compatibility16InitializeYourself().
+ /// Compatibility16InitializeYourself() is defined in Compatability16
+ /// Functions.
+ ///
+ UINT32 PciExpressBase;
+
+ ///
+ /// Maximum PCI bus number assigned.
+ ///
+ UINT8 LastPciBus;
+
+ ///
+ /// Start Address of Upper Memory Area (UMA) to be set as Read/Write. If
+ /// UmaAddress is a valid address in the shadow RAM, it also indicates that the region
+ /// from 0xC0000 to (UmaAddress - 1) can be used for Option ROM.
+ ///
+ UINT32 UmaAddress;
+
+ ///
+ /// Upper Memory Area size in bytes to be set as Read/Write. If zero, no UMA region
+ /// will be set as Read/Write (i.e. all Shadow RAM is set as Read-Only).
+ ///
+ UINT32 UmaSize;
+
+ ///
+ /// Start Address of high memory that can be used for permanent allocation. If zero,
+ /// high memory is not available for permanent allocation.
+ ///
+ UINT32 HiPermanentMemoryAddress;
+
+ ///
+ /// Size of high memory that can be used for permanent allocation in bytes. If zero,
+ /// high memory is not available for permanent allocation.
+ ///
+ UINT32 HiPermanentMemorySize;
+} EFI_COMPATIBILITY16_TABLE;
+
+///
+/// Functions provided by the CSM binary which communicate between the EfiCompatibility
+/// and Compatability16 code.
+///
+/// Inconsistent with the specification here:
+/// The member's name started with "Compatibility16" [defined in Intel Framework
+/// Compatibility Support Module Specification / 0.97 version]
+/// has been changed to "Legacy16" since keeping backward compatible.
+///
+typedef enum {
+ ///
+ /// Causes the Compatibility16 code to do any internal initialization required.
+ /// Input:
+ /// AX = Compatibility16InitializeYourself
+ /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_INIT_TABLE
+ /// Return:
+ /// AX = Return Status codes
+ ///
+ Legacy16InitializeYourself = 0x0000,
+
+ ///
+ /// Causes the Compatibility16 BIOS to perform any drive number translations to match the boot sequence.
+ /// Input:
+ /// AX = Compatibility16UpdateBbs
+ /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE
+ /// Return:
+ /// AX = Returned status codes
+ ///
+ Legacy16UpdateBbs = 0x0001,
+
+ ///
+ /// Allows the Compatibility16 code to perform any final actions before booting. The Compatibility16
+ /// code is read/write.
+ /// Input:
+ /// AX = Compatibility16PrepareToBoot
+ /// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure
+ /// Return:
+ /// AX = Returned status codes
+ ///
+ Legacy16PrepareToBoot = 0x0002,
+
+ ///
+ /// Causes the Compatibility16 BIOS to boot. The Compatibility16 code is Read/Only.
+ /// Input:
+ /// AX = Compatibility16Boot
+ /// Output:
+ /// AX = Returned status codes
+ ///
+ Legacy16Boot = 0x0003,
+
+ ///
+ /// Allows the Compatibility16 code to get the last device from which a boot was attempted. This is
+ /// stored in CMOS and is the priority number of the last attempted boot device.
+ /// Input:
+ /// AX = Compatibility16RetrieveLastBootDevice
+ /// Output:
+ /// AX = Returned status codes
+ /// BX = Priority number of the boot device.
+ ///
+ Legacy16RetrieveLastBootDevice = 0x0004,
+
+ ///
+ /// Allows the Compatibility16 code rehook INT13, INT18, and/or INT19 after dispatching a legacy OpROM.
+ /// Input:
+ /// AX = Compatibility16DispatchOprom
+ /// ES:BX = Pointer to EFI_DISPATCH_OPROM_TABLE
+ /// Output:
+ /// AX = Returned status codes
+ /// BX = Number of non-BBS-compliant devices found. Equals 0 if BBS compliant.
+ ///
+ Legacy16DispatchOprom = 0x0005,
+
+ ///
+ /// Finds a free area in the 0xFxxxx or 0xExxxx region of the specified length and returns the address
+ /// of that region.
+ /// Input:
+ /// AX = Compatibility16GetTableAddress
+ /// BX = Allocation region
+ /// 00 = Allocate from either 0xE0000 or 0xF0000 64 KB blocks.
+ /// Bit 0 = 1 Allocate from 0xF0000 64 KB block
+ /// Bit 1 = 1 Allocate from 0xE0000 64 KB block
+ /// CX = Requested length in bytes.
+ /// DX = Required address alignment. Bit mapped. First non-zero bit from the right is the alignment.
+ /// Output:
+ /// AX = Returned status codes
+ /// DS:BX = Address of the region
+ ///
+ Legacy16GetTableAddress = 0x0006,
+
+ ///
+ /// Enables the EfiCompatibility module to do any nonstandard processing of keyboard LEDs or state.
+ /// Input:
+ /// AX = Compatibility16SetKeyboardLeds
+ /// CL = LED status.
+ /// Bit 0 Scroll Lock 0 = Off
+ /// Bit 1 NumLock
+ /// Bit 2 Caps Lock
+ /// Output:
+ /// AX = Returned status codes
+ ///
+ Legacy16SetKeyboardLeds = 0x0007,
+
+ ///
+ /// Enables the EfiCompatibility module to install an interrupt handler for PCI mass media devices that
+ /// do not have an OpROM associated with them. An example is SATA.
+ /// Input:
+ /// AX = Compatibility16InstallPciHandler
+ /// ES:BX = Pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure
+ /// Output:
+ /// AX = Returned status codes
+ ///
+ Legacy16InstallPciHandler = 0x0008
+} EFI_COMPATIBILITY_FUNCTIONS;
+
+
+///
+/// EFI_DISPATCH_OPROM_TABLE
+///
+typedef struct {
+ UINT16 PnPInstallationCheckSegment; ///< A pointer to the PnpInstallationCheck data structure.
+ UINT16 PnPInstallationCheckOffset; ///< A pointer to the PnpInstallationCheck data structure.
+ UINT16 OpromSegment; ///< The segment where the OpROM was placed. Offset is assumed to be 3.
+ UINT8 PciBus; ///< The PCI bus.
+ UINT8 PciDeviceFunction; ///< The PCI device * 0x08 | PCI function.
+ UINT8 NumberBbsEntries; ///< The number of valid BBS table entries upon entry and exit. The IBV code may
+ ///< increase this number, if BBS-compliant devices also hook INTs in order to force the
+ ///< OpROM BIOS Setup to be executed.
+ UINT32 BbsTablePointer; ///< A pointer to the BBS table.
+ UINT16 RuntimeSegment; ///< The segment where the OpROM can be relocated to. If this value is 0x0000, this
+ ///< means that the relocation of this run time code is not supported.
+ ///< Inconsistent with specification here:
+ ///< The member's name "OpromDestinationSegment" [defined in Intel Framework Compatibility Support Module Specification / 0.97 version]
+ ///< has been changed to "RuntimeSegment" since keeping backward compatible.
+
+} EFI_DISPATCH_OPROM_TABLE;
+
+///
+/// EFI_TO_COMPATIBILITY16_INIT_TABLE
+///
+typedef struct {
+ ///
+ /// Starting address of memory under 1 MB. The ending address is assumed to be 640 KB or 0x9FFFF.
+ ///
+ UINT32 BiosLessThan1MB;
+
+ ///
+ /// The starting address of the high memory block.
+ ///
+ UINT32 HiPmmMemory;
+
+ ///
+ /// The length of high memory block.
+ ///
+ UINT32 HiPmmMemorySizeInBytes;
+
+ ///
+ /// The segment of the reverse thunk call code.
+ ///
+ UINT16 ReverseThunkCallSegment;
+
+ ///
+ /// The offset of the reverse thunk call code.
+ ///
+ UINT16 ReverseThunkCallOffset;
+
+ ///
+ /// The number of E820 entries copied to the Compatibility16 BIOS.
+ ///
+ UINT32 NumberE820Entries;
+
+ ///
+ /// The amount of usable memory above 1 MB, e.g., E820 type 1 memory.
+ ///
+ UINT32 OsMemoryAbove1Mb;
+
+ ///
+ /// The start of thunk code in main memory. Memory cannot be used by BIOS or PMM.
+ ///
+ UINT32 ThunkStart;
+
+ ///
+ /// The size of the thunk code.
+ ///
+ UINT32 ThunkSizeInBytes;
+
+ ///
+ /// Starting address of memory under 1 MB.
+ ///
+ UINT32 LowPmmMemory;
+
+ ///
+ /// The length of low Memory block.
+ ///
+ UINT32 LowPmmMemorySizeInBytes;
+} EFI_TO_COMPATIBILITY16_INIT_TABLE;
+
+///
+/// DEVICE_PRODUCER_SERIAL.
+///
+typedef struct {
+ UINT16 Address; ///< I/O address assigned to the serial port.
+ UINT8 Irq; ///< IRQ assigned to the serial port.
+ SERIAL_MODE Mode; ///< Mode of serial port. Values are defined below.
+} DEVICE_PRODUCER_SERIAL;
+
+///
+/// DEVICE_PRODUCER_SERIAL's modes.
+///@{
+#define DEVICE_SERIAL_MODE_NORMAL 0x00
+#define DEVICE_SERIAL_MODE_IRDA 0x01
+#define DEVICE_SERIAL_MODE_ASK_IR 0x02
+#define DEVICE_SERIAL_MODE_DUPLEX_HALF 0x00
+#define DEVICE_SERIAL_MODE_DUPLEX_FULL 0x10
+///@)
+
+///
+/// DEVICE_PRODUCER_PARALLEL.
+///
+typedef struct {
+ UINT16 Address; ///< I/O address assigned to the parallel port.
+ UINT8 Irq; ///< IRQ assigned to the parallel port.
+ UINT8 Dma; ///< DMA assigned to the parallel port.
+ PARALLEL_MODE Mode; ///< Mode of the parallel port. Values are defined below.
+} DEVICE_PRODUCER_PARALLEL;
+
+///
+/// DEVICE_PRODUCER_PARALLEL's modes.
+///@{
+#define DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY 0x00
+#define DEVICE_PARALLEL_MODE_MODE_BIDIRECTIONAL 0x01
+#define DEVICE_PARALLEL_MODE_MODE_EPP 0x02
+#define DEVICE_PARALLEL_MODE_MODE_ECP 0x03
+///@}
+
+///
+/// DEVICE_PRODUCER_FLOPPY
+///
+typedef struct {
+ UINT16 Address; ///< I/O address assigned to the floppy.
+ UINT8 Irq; ///< IRQ assigned to the floppy.
+ UINT8 Dma; ///< DMA assigned to the floppy.
+ UINT8 NumberOfFloppy; ///< Number of floppies in the system.
+} DEVICE_PRODUCER_FLOPPY;
+
+///
+/// LEGACY_DEVICE_FLAGS
+///
+typedef struct {
+ UINT32 A20Kybd : 1; ///< A20 controller by keyboard controller.
+ UINT32 A20Port90 : 1; ///< A20 controlled by port 0x92.
+ UINT32 Reserved : 30; ///< Reserved for future usage.
+} LEGACY_DEVICE_FLAGS;
+
+///
+/// DEVICE_PRODUCER_DATA_HEADER
+///
+typedef struct {
+ DEVICE_PRODUCER_SERIAL Serial[4]; ///< Data for serial port x. Type DEVICE_PRODUCER_SERIAL is defined below.
+ DEVICE_PRODUCER_PARALLEL Parallel[3]; ///< Data for parallel port x. Type DEVICE_PRODUCER_PARALLEL is defined below.
+ DEVICE_PRODUCER_FLOPPY Floppy; ///< Data for floppy. Type DEVICE_PRODUCER_FLOPPY is defined below.
+ UINT8 MousePresent; ///< Flag to indicate if mouse is present.
+ LEGACY_DEVICE_FLAGS Flags; ///< Miscellaneous Boolean state information passed to CSM.
+} DEVICE_PRODUCER_DATA_HEADER;
+
+///
+/// ATAPI_IDENTIFY
+///
+typedef struct {
+ UINT16 Raw[256]; ///< Raw data from the IDE IdentifyDrive command.
+} ATAPI_IDENTIFY;
+
+///
+/// HDD_INFO
+///
+typedef struct {
+ ///
+ /// Status of IDE device. Values are defined below. There is one HDD_INFO structure
+ /// per IDE controller. The IdentifyDrive is per drive. Index 0 is master and index
+ /// 1 is slave.
+ ///
+ UINT16 Status;
+
+ ///
+ /// PCI bus of IDE controller.
+ ///
+ UINT32 Bus;
+
+ ///
+ /// PCI device of IDE controller.
+ ///
+ UINT32 Device;
+
+ ///
+ /// PCI function of IDE controller.
+ ///
+ UINT32 Function;
+
+ ///
+ /// Command ports base address.
+ ///
+ UINT16 CommandBaseAddress;
+
+ ///
+ /// Control ports base address.
+ ///
+ UINT16 ControlBaseAddress;
+
+ ///
+ /// Bus master address.
+ ///
+ UINT16 BusMasterAddress;
+
+ UINT8 HddIrq;
+
+ ///
+ /// Data that identifies the drive data; one per possible attached drive.
+ ///
+ ATAPI_IDENTIFY IdentifyDrive[2];
+} HDD_INFO;
+
+///
+/// HDD_INFO status bits
+///
+#define HDD_PRIMARY 0x01
+#define HDD_SECONDARY 0x02
+#define HDD_MASTER_ATAPI_CDROM 0x04
+#define HDD_SLAVE_ATAPI_CDROM 0x08
+#define HDD_MASTER_IDE 0x20
+#define HDD_SLAVE_IDE 0x40
+#define HDD_MASTER_ATAPI_ZIPDISK 0x10
+#define HDD_SLAVE_ATAPI_ZIPDISK 0x80
+
+///
+/// BBS_STATUS_FLAGS;\.
+///
+typedef struct {
+ UINT16 OldPosition : 4; ///< Prior priority.
+ UINT16 Reserved1 : 4; ///< Reserved for future use.
+ UINT16 Enabled : 1; ///< If 0, ignore this entry.
+ UINT16 Failed : 1; ///< 0 = Not known if boot failure occurred.
+ ///< 1 = Boot attempted failed.
+
+ ///
+ /// State of media present.
+ /// 00 = No bootable media is present in the device.
+ /// 01 = Unknown if a bootable media present.
+ /// 10 = Media is present and appears bootable.
+ /// 11 = Reserved.
+ ///
+ UINT16 MediaPresent : 2;
+ UINT16 Reserved2 : 4; ///< Reserved for future use.
+} BBS_STATUS_FLAGS;
+
+///
+/// BBS_TABLE, device type values & boot priority values.
+///
+typedef struct {
+ ///
+ /// The boot priority for this boot device. Values are defined below.
+ ///
+ UINT16 BootPriority;
+
+ ///
+ /// The PCI bus for this boot device.
+ ///
+ UINT32 Bus;
+
+ ///
+ /// The PCI device for this boot device.
+ ///
+ UINT32 Device;
+
+ ///
+ /// The PCI function for the boot device.
+ ///
+ UINT32 Function;
+
+ ///
+ /// The PCI class for this boot device.
+ ///
+ UINT8 Class;
+
+ ///
+ /// The PCI Subclass for this boot device.
+ ///
+ UINT8 SubClass;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing the manufacturer.
+ ///
+ UINT16 MfgStringOffset;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing the manufacturer.
+ ///
+ UINT16 MfgStringSegment;
+
+ ///
+ /// BBS device type. BBS device types are defined below.
+ ///
+ UINT16 DeviceType;
+
+ ///
+ /// Status of this boot device. Type BBS_STATUS_FLAGS is defined below.
+ ///
+ BBS_STATUS_FLAGS StatusFlags;
+
+ ///
+ /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for
+ /// BCV devices.
+ ///
+ UINT16 BootHandlerOffset;
+
+ ///
+ /// Segment:Offset address of boot loader for IPL devices or install INT13 handler for
+ /// BCV devices.
+ ///
+ UINT16 BootHandlerSegment;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing this device.
+ ///
+ UINT16 DescStringOffset;
+
+ ///
+ /// Segment:offset address of an ASCIIZ description string describing this device.
+ ///
+ UINT16 DescStringSegment;
+
+ ///
+ /// Reserved.
+ ///
+ UINT32 InitPerReserved;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq13Handler;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq18Handler;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq19Handler;
+
+ ///
+ /// The use of these fields is IBV dependent. They can be used to flag that an OpROM
+ /// has hooked the specified IRQ. The OpROM may be BBS compliant as some SCSI
+ /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIOS Setup
+ ///
+ UINT32 AdditionalIrq40Handler;
+ UINT8 AssignedDriveNumber;
+ UINT32 AdditionalIrq41Handler;
+ UINT32 AdditionalIrq46Handler;
+ UINT32 IBV1;
+ UINT32 IBV2;
+} BBS_TABLE;
+
+///
+/// BBS device type values
+///@{
+#define BBS_FLOPPY 0x01
+#define BBS_HARDDISK 0x02
+#define BBS_CDROM 0x03
+#define BBS_PCMCIA 0x04
+#define BBS_USB 0x05
+#define BBS_EMBED_NETWORK 0x06
+#define BBS_BEV_DEVICE 0x80
+#define BBS_UNKNOWN 0xff
+///@}
+
+///
+/// BBS boot priority values
+///@{
+#define BBS_DO_NOT_BOOT_FROM 0xFFFC
+#define BBS_LOWEST_PRIORITY 0xFFFD
+#define BBS_UNPRIORITIZED_ENTRY 0xFFFE
+#define BBS_IGNORE_ENTRY 0xFFFF
+///@}
+
+///
+/// SMM_ATTRIBUTES
+///
+typedef struct {
+ ///
+ /// Access mechanism used to generate the soft SMI. Defined types are below. The other
+ /// values are reserved for future usage.
+ ///
+ UINT16 Type : 3;
+
+ ///
+ /// The size of "port" in bits. Defined values are below.
+ ///
+ UINT16 PortGranularity : 3;
+
+ ///
+ /// The size of data in bits. Defined values are below.
+ ///
+ UINT16 DataGranularity : 3;
+
+ ///
+ /// Reserved for future use.
+ ///
+ UINT16 Reserved : 7;
+} SMM_ATTRIBUTES;
+
+///
+/// SMM_ATTRIBUTES type values.
+///@{
+#define STANDARD_IO 0x00
+#define STANDARD_MEMORY 0x01
+///@}
+
+///
+/// SMM_ATTRIBUTES port size constants.
+///@{
+#define PORT_SIZE_8 0x00
+#define PORT_SIZE_16 0x01
+#define PORT_SIZE_32 0x02
+#define PORT_SIZE_64 0x03
+///@}
+
+///
+/// SMM_ATTRIBUTES data size constants.
+///@{
+#define DATA_SIZE_8 0x00
+#define DATA_SIZE_16 0x01
+#define DATA_SIZE_32 0x02
+#define DATA_SIZE_64 0x03
+///@}
+
+///
+/// SMM_FUNCTION & relating constants.
+///
+typedef struct {
+ UINT16 Function : 15;
+ UINT16 Owner : 1;
+} SMM_FUNCTION;
+
+///
+/// SMM_FUNCTION Function constants.
+///@{
+#define INT15_D042 0x0000
+#define GET_USB_BOOT_INFO 0x0001
+#define DMI_PNP_50_57 0x0002
+///@}
+
+///
+/// SMM_FUNCTION Owner constants.
+///@{
+#define STANDARD_OWNER 0x0
+#define OEM_OWNER 0x1
+///@}
+
+///
+/// This structure assumes both port and data sizes are 1. SmmAttribute must be
+/// properly to reflect that assumption.
+///
+typedef struct {
+ ///
+ /// Describes the access mechanism, SmmPort, and SmmData sizes. Type
+ /// SMM_ATTRIBUTES is defined below.
+ ///
+ SMM_ATTRIBUTES SmmAttributes;
+
+ ///
+ /// Function Soft SMI is to perform. Type SMM_FUNCTION is defined below.
+ ///
+ SMM_FUNCTION SmmFunction;
+
+ ///
+ /// SmmPort size depends upon SmmAttributes and ranges from2 bytes to 16 bytes.
+ ///
+ UINT8 SmmPort;
+
+ ///
+ /// SmmData size depends upon SmmAttributes and ranges from2 bytes to 16 bytes.
+ ///
+ UINT8 SmmData;
+} SMM_ENTRY;
+
+///
+/// SMM_TABLE
+///
+typedef struct {
+ UINT16 NumSmmEntries; ///< Number of entries represented by SmmEntry.
+ SMM_ENTRY SmmEntry; ///< One entry per function. Type SMM_ENTRY is defined below.
+} SMM_TABLE;
+
+///
+/// UDC_ATTRIBUTES
+///
+typedef struct {
+ ///
+ /// This bit set indicates that the ServiceAreaData is valid.
+ ///
+ UINT8 DirectoryServiceValidity : 1;
+
+ ///
+ /// This bit set indicates to use the Reserve Area Boot Code Address (RACBA) only if
+ /// DirectoryServiceValidity is 0.
+ ///
+ UINT8 RabcaUsedFlag : 1;
+
+ ///
+ /// This bit set indicates to execute hard disk diagnostics.
+ ///
+ UINT8 ExecuteHddDiagnosticsFlag : 1;
+
+ ///
+ /// Reserved for future use. Set to 0.
+ ///
+ UINT8 Reserved : 5;
+} UDC_ATTRIBUTES;
+
+///
+/// UD_TABLE
+///
+typedef struct {
+ ///
+ /// This field contains the bit-mapped attributes of the PARTIES information. Type
+ /// UDC_ATTRIBUTES is defined below.
+ ///
+ UDC_ATTRIBUTES Attributes;
+
+ ///
+ /// This field contains the zero-based device on which the selected
+ /// ServiceDataArea is present. It is 0 for master and 1 for the slave device.
+ ///
+ UINT8 DeviceNumber;
+
+ ///
+ /// This field contains the zero-based index into the BbsTable for the parent device.
+ /// This index allows the user to reference the parent device information such as PCI
+ /// bus, device function.
+ ///
+ UINT8 BbsTableEntryNumberForParentDevice;
+
+ ///
+ /// This field contains the zero-based index into the BbsTable for the boot entry.
+ ///
+ UINT8 BbsTableEntryNumberForBoot;
+
+ ///
+ /// This field contains the zero-based index into the BbsTable for the HDD diagnostics entry.
+ ///
+ UINT8 BbsTableEntryNumberForHddDiag;
+
+ ///
+ /// The raw Beer data.
+ ///
+ UINT8 BeerData[128];
+
+ ///
+ /// The raw data of selected service area.
+ ///
+ UINT8 ServiceAreaData[64];
+} UD_TABLE;
+
+#define EFI_TO_LEGACY_MAJOR_VERSION 0x02
+#define EFI_TO_LEGACY_MINOR_VERSION 0x00
+#define MAX_IDE_CONTROLLER 8
+
+///
+/// EFI_TO_COMPATIBILITY16_BOOT_TABLE
+///
+typedef struct {
+ UINT16 MajorVersion; ///< The EfiCompatibility major version number.
+ UINT16 MinorVersion; ///< The EfiCompatibility minor version number.
+ UINT32 AcpiTable; ///< The location of the RSDT ACPI table. < 4G range.
+ UINT32 SmbiosTable; ///< The location of the SMBIOS table in EFI memory. < 4G range.
+ UINT32 SmbiosTableLength;
+ //
+ // Legacy SIO state
+ //
+ DEVICE_PRODUCER_DATA_HEADER SioData; ///< Standard traditional device information.
+ UINT16 DevicePathType; ///< The default boot type.
+ UINT16 PciIrqMask; ///< Mask of which IRQs have been assigned to PCI.
+ UINT32 NumberE820Entries; ///< Number of E820 entries. The number can change from the
+ ///< Compatibility16InitializeYourself() function.
+ //
+ // Controller & Drive Identify[2] per controller information
+ //
+ HDD_INFO HddInfo[MAX_IDE_CONTROLLER]; ///< Hard disk drive information, including raw Identify Drive data.
+ UINT32 NumberBbsEntries; ///< Number of entries in the BBS table
+ UINT32 BbsTable; ///< A pointer to the BBS table. Type BBS_TABLE is defined below.
+ UINT32 SmmTable; ///< A pointer to the SMM table. Type SMM_TABLE is defined below.
+ UINT32 OsMemoryAbove1Mb; ///< The amount of usable memory above 1 MB, i.e. E820 type 1 memory. This value can
+ ///< differ from the value in EFI_TO_COMPATIBILITY16_INIT_TABLE as more
+ ///< memory may have been discovered.
+ UINT32 UnconventionalDeviceTable; ///< Information to boot off an unconventional device like a PARTIES partition. Type
+ ///< UD_TABLE is defined below.
+} EFI_TO_COMPATIBILITY16_BOOT_TABLE;
+
+///
+/// EFI_LEGACY_INSTALL_PCI_HANDLER
+///
+typedef struct {
+ UINT8 PciBus; ///< The PCI bus of the device.
+ UINT8 PciDeviceFun; ///< The PCI device in bits 7:3 and function in bits 2:0.
+ UINT8 PciSegment; ///< The PCI segment of the device.
+ UINT8 PciClass; ///< The PCI class code of the device.
+ UINT8 PciSubclass; ///< The PCI subclass code of the device.
+ UINT8 PciInterface; ///< The PCI interface code of the device.
+ //
+ // Primary section
+ //
+ UINT8 PrimaryIrq; ///< The primary device IRQ.
+ UINT8 PrimaryReserved; ///< Reserved.
+ UINT16 PrimaryControl; ///< The primary device control I/O base.
+ UINT16 PrimaryBase; ///< The primary device I/O base.
+ UINT16 PrimaryBusMaster; ///< The primary device bus master I/O base.
+ //
+ // Secondary Section
+ //
+ UINT8 SecondaryIrq; ///< The secondary device IRQ.
+ UINT8 SecondaryReserved; ///< Reserved.
+ UINT16 SecondaryControl; ///< The secondary device control I/O base.
+ UINT16 SecondaryBase; ///< The secondary device I/O base.
+ UINT16 SecondaryBusMaster; ///< The secondary device bus master I/O base.
+} EFI_LEGACY_INSTALL_PCI_HANDLER;
+
+//
+// Restore default pack value
+//
+#pragma pack()
+
+#define EFI_LEGACY_BIOS_PROTOCOL_GUID \
+ { \
+ 0xdb9a1e3d, 0x45cb, 0x4abb, {0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d } \
+ }
+
+typedef struct _EFI_LEGACY_BIOS_PROTOCOL EFI_LEGACY_BIOS_PROTOCOL;
+
+///
+/// Flags returned by CheckPciRom().
+///
+#define NO_ROM 0x00
+#define ROM_FOUND 0x01
+#define VALID_LEGACY_ROM 0x02
+#define ROM_WITH_CONFIG 0x04 ///< Not defined in the Framework CSM Specification.
+
+///
+/// The following macros do not appear in the Framework CSM Specification and
+/// are kept for backward compatibility only. They convert 32-bit address (_Adr)
+/// to Segment:Offset 16-bit form.
+///
+///@{
+#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000)
+#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xffff)
+///@}
+
+#define CARRY_FLAG 0x01
+
+///
+/// EFI_EFLAGS_REG
+///
+typedef struct {
+ UINT32 CF:1;
+ UINT32 Reserved1:1;
+ UINT32 PF:1;
+ UINT32 Reserved2:1;
+ UINT32 AF:1;
+ UINT32 Reserved3:1;
+ UINT32 ZF:1;
+ UINT32 SF:1;
+ UINT32 TF:1;
+ UINT32 IF:1;
+ UINT32 DF:1;
+ UINT32 OF:1;
+ UINT32 IOPL:2;
+ UINT32 NT:1;
+ UINT32 Reserved4:2;
+ UINT32 VM:1;
+ UINT32 Reserved5:14;
+} EFI_EFLAGS_REG;
+
+///
+/// EFI_DWORD_REGS
+///
+typedef struct {
+ UINT32 EAX;
+ UINT32 EBX;
+ UINT32 ECX;
+ UINT32 EDX;
+ UINT32 ESI;
+ UINT32 EDI;
+ EFI_EFLAGS_REG EFlags;
+ UINT16 ES;
+ UINT16 CS;
+ UINT16 SS;
+ UINT16 DS;
+ UINT16 FS;
+ UINT16 GS;
+ UINT32 EBP;
+ UINT32 ESP;
+} EFI_DWORD_REGS;
+
+///
+/// EFI_FLAGS_REG
+///
+typedef struct {
+ UINT16 CF:1;
+ UINT16 Reserved1:1;
+ UINT16 PF:1;
+ UINT16 Reserved2:1;
+ UINT16 AF:1;
+ UINT16 Reserved3:1;
+ UINT16 ZF:1;
+ UINT16 SF:1;
+ UINT16 TF:1;
+ UINT16 IF:1;
+ UINT16 DF:1;
+ UINT16 OF:1;
+ UINT16 IOPL:2;
+ UINT16 NT:1;
+ UINT16 Reserved4:1;
+} EFI_FLAGS_REG;
+
+///
+/// EFI_WORD_REGS
+///
+typedef struct {
+ UINT16 AX;
+ UINT16 ReservedAX;
+ UINT16 BX;
+ UINT16 ReservedBX;
+ UINT16 CX;
+ UINT16 ReservedCX;
+ UINT16 DX;
+ UINT16 ReservedDX;
+ UINT16 SI;
+ UINT16 ReservedSI;
+ UINT16 DI;
+ UINT16 ReservedDI;
+ EFI_FLAGS_REG Flags;
+ UINT16 ReservedFlags;
+ UINT16 ES;
+ UINT16 CS;
+ UINT16 SS;
+ UINT16 DS;
+ UINT16 FS;
+ UINT16 GS;
+ UINT16 BP;
+ UINT16 ReservedBP;
+ UINT16 SP;
+ UINT16 ReservedSP;
+} EFI_WORD_REGS;
+
+///
+/// EFI_BYTE_REGS
+///
+typedef struct {
+ UINT8 AL, AH;
+ UINT16 ReservedAX;
+ UINT8 BL, BH;
+ UINT16 ReservedBX;
+ UINT8 CL, CH;
+ UINT16 ReservedCX;
+ UINT8 DL, DH;
+ UINT16 ReservedDX;
+} EFI_BYTE_REGS;
+
+///
+/// EFI_IA32_REGISTER_SET
+///
+typedef union {
+ EFI_DWORD_REGS E;
+ EFI_WORD_REGS X;
+ EFI_BYTE_REGS H;
+} EFI_IA32_REGISTER_SET;
+
+/**
+ Thunk to 16-bit real mode and execute a software interrupt with a vector
+ of BiosInt. Regs will contain the 16-bit register context on entry and
+ exit.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] BiosInt The processor interrupt vector to invoke.
+ @param[in,out] Reg Register contexted passed into (and returned) from thunk to
+ 16-bit mode.
+
+ @retval TRUE Thunk completed with no BIOS errors in the target code. See Regs for status.
+ @retval FALSE There was a BIOS error in the target code.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_LEGACY_BIOS_INT86)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT8 BiosInt,
+ IN OUT EFI_IA32_REGISTER_SET *Regs
+ );
+
+/**
+ Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the
+ 16-bit register context on entry and exit. Arguments can be passed on
+ the Stack argument
+
+ @param[in] This The protocol instance pointer.
+ @param[in] Segment The segemnt of 16-bit mode call.
+ @param[in] Offset The offset of 16-bit mdoe call.
+ @param[in] Reg Register contexted passed into (and returned) from thunk to
+ 16-bit mode.
+ @param[in] Stack The caller allocated stack used to pass arguments.
+ @param[in] StackSize The size of Stack in bytes.
+
+ @retval FALSE Thunk completed with no BIOS errors in the target code. See Regs for status. @retval TRUE There was a BIOS error in the target code.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_LEGACY_BIOS_FARCALL86)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN EFI_IA32_REGISTER_SET *Regs,
+ IN VOID *Stack,
+ IN UINTN StackSize
+ );
+
+/**
+ Test to see if a legacy PCI ROM exists for this device. Optionally return
+ the Legacy ROM instance for this PCI device.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded
+ @param[out] RomImage Return the legacy PCI ROM for this device.
+ @param[out] RomSize The size of ROM Image.
+ @param[out] Flags Indicates if ROM found and if PC-AT. Multiple bits can be set as follows:
+ - 00 = No ROM.
+ - 01 = ROM Found.
+ - 02 = ROM is a valid legacy ROM.
+
+ @retval EFI_SUCCESS The Legacy Option ROM availible for this device
+ @retval EFI_UNSUPPORTED The Legacy Option ROM is not supported.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_CHECK_ROM)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN EFI_HANDLE PciHandle,
+ OUT VOID **RomImage, OPTIONAL
+ OUT UINTN *RomSize, OPTIONAL
+ OUT UINTN *Flags
+ );
+
+/**
+ Load a legacy PC-AT OPROM on the PciHandle device. Return information
+ about how many disks were added by the OPROM and the shadow address and
+ size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:
+
+ @param[in] This The protocol instance pointer.
+ @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded.
+ This value is NULL if RomImage is non-NULL. This is the normal
+ case.
+ @param[in] RomImage A PCI PC-AT ROM image. This argument is non-NULL if there is
+ no hardware associated with the ROM and thus no PciHandle,
+ otherwise is must be NULL.
+ Example is PXE base code.
+ @param[out] Flags The type of ROM discovered. Multiple bits can be set, as follows:
+ - 00 = No ROM.
+ - 01 = ROM found.
+ - 02 = ROM is a valid legacy ROM.
+ @param[out] DiskStart The disk number of first device hooked by the ROM. If DiskStart
+ is the same as DiskEnd no disked were hooked.
+ @param[out] DiskEnd disk number of the last device hooked by the ROM.
+ @param[out] RomShadowAddress Shadow address of PC-AT ROM.
+ @param[out] RomShadowSize Size of RomShadowAddress in bytes.
+
+ @retval EFI_SUCCESS Thunk completed, see Regs for status.
+ @retval EFI_INVALID_PARAMETER PciHandle not found
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_INSTALL_ROM)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN EFI_HANDLE PciHandle,
+ IN VOID **RomImage,
+ OUT UINTN *Flags,
+ OUT UINT8 *DiskStart, OPTIONAL
+ OUT UINT8 *DiskEnd, OPTIONAL
+ OUT VOID **RomShadowAddress, OPTIONAL
+ OUT UINT32 *ShadowedRomSize OPTIONAL
+ );
+
+/**
+ This function attempts to traditionally boot the specified BootOption. If the EFI context has
+ been compromised, this function will not return. This procedure is not used for loading an EFI-aware
+ OS off a traditional device. The following actions occur:
+ - Get EFI SMBIOS data structures, convert them to a traditional format, and copy to
+ Compatibility16.
+ - Get a pointer to ACPI data structures and copy the Compatibility16 RSD PTR to F0000 block.
+ - Find the traditional SMI handler from a firmware volume and register the traditional SMI
+ handler with the EFI SMI handler.
+ - Build onboard IDE information and pass this information to the Compatibility16 code.
+ - Make sure all PCI Interrupt Line registers are programmed to match 8259.
+ - Reconfigure SIO devices from EFI mode (polled) into traditional mode (interrupt driven).
+ - Shadow all PCI ROMs.
+ - Set up BDA and EBDA standard areas before the legacy boot.
+ - Construct the Compatibility16 boot memory map and pass it to the Compatibility16 code.
+ - Invoke the Compatibility16 table function Compatibility16PrepareToBoot(). This
+ invocation causes a thunk into the Compatibility16 code, which sets all appropriate internal
+ data structures. The boot device list is a parameter.
+ - Invoke the Compatibility16 Table function Compatibility16Boot(). This invocation
+ causes a thunk into the Compatibility16 code, which does an INT19.
+ - If the Compatibility16Boot() function returns, then the boot failed in a graceful
+ manner--meaning that the EFI code is still valid. An ungraceful boot failure causes a reset because the state
+ of EFI code is unknown.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] BootOption The EFI Device Path from BootXXXX variable.
+ @param[in] LoadOptionSize The size of LoadOption in size.
+ @param[in] LoadOption LThe oadOption from BootXXXX variable.
+
+ @retval EFI_DEVICE_ERROR Failed to boot from any boot device and memory is uncorrupted. Note: This function normally does not returns. It will either boot the OS or reset the system if memory has been "corrupted" by loading a boot sector and passing control to it.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_BOOT)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN BBS_BBS_DEVICE_PATH *BootOption,
+ IN UINT32 LoadOptionsSize,
+ IN VOID *LoadOptions
+ );
+
+/**
+ This function takes the Leds input parameter and sets/resets the BDA accordingly.
+ Leds is also passed to Compatibility16 code, in case any special processing is required.
+ This function is normally called from EFI Setup drivers that handle user-selectable
+ keyboard options such as boot with NUM LOCK on/off. This function does not
+ touch the keyboard or keyboard LEDs but only the BDA.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] Leds The status of current Scroll, Num & Cap lock LEDS:
+ - Bit 0 is Scroll Lock 0 = Not locked.
+ - Bit 1 is Num Lock.
+ - Bit 2 is Caps Lock.
+
+ @retval EFI_SUCCESS The BDA was updated successfully.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT8 Leds
+ );
+
+/**
+ Retrieve legacy BBS info and assign boot priority.
+
+ @param[in] This The protocol instance pointer.
+ @param[out] HddCount The number of HDD_INFO structures.
+ @param[out] HddInfo Onboard IDE controller information.
+ @param[out] BbsCount The number of BBS_TABLE structures.
+ @param[in,out] BbsTable Points to List of BBS_TABLE.
+
+ @retval EFI_SUCCESS Tables were returned.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_GET_BBS_INFO)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ OUT UINT16 *HddCount,
+ OUT HDD_INFO **HddInfo,
+ OUT UINT16 *BbsCount,
+ IN OUT BBS_TABLE **BbsTable
+ );
+
+/**
+ Assign drive number to legacy HDD drives prior to booting an EFI
+ aware OS so the OS can access drives without an EFI driver.
+
+ @param[in] This The protocol instance pointer.
+ @param[out] BbsCount The number of BBS_TABLE structures
+ @param[out] BbsTable List of BBS entries
+
+ @retval EFI_SUCCESS Drive numbers assigned.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ OUT UINT16 *BbsCount,
+ OUT BBS_TABLE **BbsTable
+ );
+
+/**
+ To boot from an unconventional device like parties and/or execute
+ HDD diagnostics.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] Attributes How to interpret the other input parameters.
+ @param[in] BbsEntry The 0-based index into the BbsTable for the parent
+ device.
+ @param[in] BeerData A pointer to the 128 bytes of ram BEER data.
+ @param[in] ServiceAreaData A pointer to the 64 bytes of raw Service Area data. The
+ caller must provide a pointer to the specific Service
+ Area and not the start all Service Areas.
+
+ @retval EFI_INVALID_PARAMETER If error. Does NOT return if no error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UDC_ATTRIBUTES Attributes,
+ IN UINTN BbsEntry,
+ IN VOID *BeerData,
+ IN VOID *ServiceAreaData
+ );
+
+/**
+ Shadow all legacy16 OPROMs that haven't been shadowed.
+ Warning: Use this with caution. This routine disconnects all EFI
+ drivers. If used externally, then the caller must re-connect EFI
+ drivers.
+
+ @param[in] This The protocol instance pointer.
+
+ @retval EFI_SUCCESS OPROMs were shadowed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This
+ );
+
+/**
+ Get a region from the LegacyBios for S3 usage.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] LegacyMemorySize The size of required region.
+ @param[in] Region The region to use.
+ 00 = Either 0xE0000 or 0xF0000 block.
+ - Bit0 = 1 0xF0000 block.
+ - Bit1 = 1 0xE0000 block.
+ @param[in] Alignment Address alignment. Bit mapped. The first non-zero
+ bit from right is alignment.
+ @param[out] LegacyMemoryAddress The Region Assigned
+
+ @retval EFI_SUCCESS The Region was assigned.
+ @retval EFI_ACCESS_DENIED The function was previously invoked.
+ @retval Other The Region was not assigned.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_GET_LEGACY_REGION)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINTN LegacyMemorySize,
+ IN UINTN Region,
+ IN UINTN Alignment,
+ OUT VOID **LegacyMemoryAddress
+ );
+
+/**
+ Get a region from the LegacyBios for Tiano usage. Can only be invoked once.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] LegacyMemorySize The size of data to copy.
+ @param[in] LegacyMemoryAddress The Legacy Region destination address.
+ Note: must be in region assigned by
+ LegacyBiosGetLegacyRegion.
+ @param[in] LegacyMemorySourceAddress The source of the data to copy.
+
+ @retval EFI_SUCCESS The Region assigned.
+ @retval EFI_ACCESS_DENIED Destination was outside an assigned region.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_BIOS_COPY_LEGACY_REGION)(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINTN LegacyMemorySize,
+ IN VOID *LegacyMemoryAddress,
+ IN VOID *LegacyMemorySourceAddress
+ );
+
+///
+/// Abstracts the traditional BIOS from the rest of EFI. The LegacyBoot()
+/// member function allows the BDS to support booting a traditional OS.
+/// EFI thunks drivers that make EFI bindings for BIOS INT services use
+/// all the other member functions.
+///
+struct _EFI_LEGACY_BIOS_PROTOCOL {
+ ///
+ /// Performs traditional software INT. See the Int86() function description.
+ ///
+ EFI_LEGACY_BIOS_INT86 Int86;
+
+ ///
+ /// Performs a far call into Compatibility16 or traditional OpROM code.
+ ///
+ EFI_LEGACY_BIOS_FARCALL86 FarCall86;
+
+ ///
+ /// Checks if a traditional OpROM exists for this device.
+ ///
+ EFI_LEGACY_BIOS_CHECK_ROM CheckPciRom;
+
+ ///
+ /// Loads a traditional OpROM in traditional OpROM address space.
+ ///
+ EFI_LEGACY_BIOS_INSTALL_ROM InstallPciRom;
+
+ ///
+ /// Boots a traditional OS.
+ ///
+ EFI_LEGACY_BIOS_BOOT LegacyBoot;
+
+ ///
+ /// Updates BDA to reflect the current EFI keyboard LED status.
+ ///
+ EFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS UpdateKeyboardLedStatus;
+
+ ///
+ /// Allows an external agent, such as BIOS Setup, to get the BBS data.
+ ///
+ EFI_LEGACY_BIOS_GET_BBS_INFO GetBbsInfo;
+
+ ///
+ /// Causes all legacy OpROMs to be shadowed.
+ ///
+ EFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS ShadowAllLegacyOproms;
+
+ ///
+ /// Performs all actions prior to boot. Used when booting an EFI-aware OS
+ /// rather than a legacy OS.
+ ///
+ EFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI PrepareToBootEfi;
+
+ ///
+ /// Allows EFI to reserve an area in the 0xE0000 or 0xF0000 block.
+ ///
+ EFI_LEGACY_BIOS_GET_LEGACY_REGION GetLegacyRegion;
+
+ ///
+ /// Allows EFI to copy data to the area specified by GetLegacyRegion.
+ ///
+ EFI_LEGACY_BIOS_COPY_LEGACY_REGION CopyLegacyRegion;
+
+ ///
+ /// Allows the user to boot off an unconventional device such as a PARTIES partition.
+ ///
+ EFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE BootUnconventionalDevice;
+};
+
+extern EFI_GUID gEfiLegacyBiosProtocolGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyInterrupt.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyInterrupt.h
new file mode 100644
index 0000000000..f06836a97c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelFrameworkPkg/Include/Protocol/LegacyInterrupt.h
@@ -0,0 +1,128 @@
+/** @file
+ This protocol abstracts the PIRQ programming from the generic EFI Compatibility Support Modules (CSMs).
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This protocol is defined in Framework for the EFI Compatibility Support Module specification.
+ Version 0.97.
+
+**/
+
+#ifndef _EFI_LEGACY_INTERRUPT_H_
+#define _EFI_LEGACY_INTERRUPT_H_
+
+
+#define EFI_LEGACY_INTERRUPT_PROTOCOL_GUID \
+ { \
+ 0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe } \
+ }
+
+typedef struct _EFI_LEGACY_INTERRUPT_PROTOCOL EFI_LEGACY_INTERRUPT_PROTOCOL;
+
+/**
+ Get the number of PIRQs this hardware supports.
+
+ @param This The protocol instance pointer.
+ @param NumberPirsq The number of PIRQs that are supported.
+
+ @retval EFI_SUCCESS The number of PIRQs was returned successfully.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_INTERRUPT_GET_NUMBER_PIRQS)(
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ );
+
+/**
+ Gets the PCI location associated with this protocol.
+
+ @param This The Protocol instance pointer.
+ @param Bus The PCI Bus.
+ @param Device The PCI Device.
+ @param Function The PCI Function.
+
+ @retval EFI_SUCCESS The Bus, Device, and Function were returned successfully.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_INTERRUPT_GET_LOCATION)(
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ );
+
+/**
+ Read the PIRQ register and return the data
+
+ @param This The protocol instance pointer.
+ @param PirqNumber The PIRQ register to read.
+ @param PirqData The data read.
+
+ @retval EFI_SUCCESS The data was read.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_INTERRUPT_READ_PIRQ)(
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ );
+
+/**
+ Write the specified PIRQ register with the given data.
+
+ @param This The protocol instance pointer.
+ @param PirqNumber A PIRQ register to read.
+ @param PirqData The data to write.
+
+ @retval EFI_SUCCESS The PIRQ was programmed.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LEGACY_INTERRUPT_WRITE_PIRQ)(
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ );
+
+struct _EFI_LEGACY_INTERRUPT_PROTOCOL {
+ ///
+ /// Gets the number of PIRQs supported.
+ ///
+ EFI_LEGACY_INTERRUPT_GET_NUMBER_PIRQS GetNumberPirqs;
+
+ ///
+ /// Gets the PCI bus, device, and function that is associated with this protocol.
+ ///
+ EFI_LEGACY_INTERRUPT_GET_LOCATION GetLocation;
+
+ ///
+ /// Reads the indicated PIRQ register.
+ ///
+ EFI_LEGACY_INTERRUPT_READ_PIRQ ReadPirq;
+
+ ///
+ /// Writes to the indicated PIRQ register.
+ ///
+ EFI_LEGACY_INTERRUPT_WRITE_PIRQ WritePirq;
+};
+
+extern EFI_GUID gEfiLegacyInterruptProtocolGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelGraphicsPeimVbt/PeiVbt.bin b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelGraphicsPeimVbt/PeiVbt.bin
new file mode 100644
index 0000000000..72da3dee1b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/IntelGraphicsPeimVbt/PeiVbt.bin
Binary files differ
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/AcpiS3Context.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/AcpiS3Context.h
new file mode 100644
index 0000000000..8f78e284f6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/AcpiS3Context.h
@@ -0,0 +1,73 @@
+/** @file
+ Definitions for data structures used in S3 resume.
+
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ACPI_S3_DATA_H_
+#define _ACPI_S3_DATA_H_
+
+#include <Library/BaseLib.h>
+
+#define SMM_S3_RESUME_SMM_32 SIGNATURE_64 ('S','M','M','S','3','_','3','2')
+#define SMM_S3_RESUME_SMM_64 SIGNATURE_64 ('S','M','M','S','3','_','6','4')
+
+#pragma pack(1)
+
+typedef struct {
+ UINT64 Signature;
+ EFI_PHYSICAL_ADDRESS SmmS3ResumeEntryPoint;
+ EFI_PHYSICAL_ADDRESS SmmS3StackBase;
+ UINT64 SmmS3StackSize;
+ UINT64 SmmS3Cr0;
+ UINT64 SmmS3Cr3;
+ UINT64 SmmS3Cr4;
+ UINT16 ReturnCs;
+ EFI_PHYSICAL_ADDRESS ReturnEntryPoint;
+ EFI_PHYSICAL_ADDRESS ReturnContext1;
+ EFI_PHYSICAL_ADDRESS ReturnContext2;
+ EFI_PHYSICAL_ADDRESS ReturnStackPointer;
+ EFI_PHYSICAL_ADDRESS Smst;
+} SMM_S3_RESUME_STATE;
+
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS AcpiFacsTable;
+ EFI_PHYSICAL_ADDRESS IdtrProfile;
+ EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;
+ EFI_PHYSICAL_ADDRESS BootScriptStackBase;
+ UINT64 BootScriptStackSize;
+ EFI_PHYSICAL_ADDRESS S3DebugBufferAddress;
+} ACPI_S3_CONTEXT;
+
+typedef struct {
+ UINT16 ReturnCs;
+ UINT64 ReturnStatus;
+ EFI_PHYSICAL_ADDRESS ReturnEntryPoint;
+ EFI_PHYSICAL_ADDRESS ReturnStackPointer;
+ EFI_PHYSICAL_ADDRESS AsmTransferControl;
+ IA32_DESCRIPTOR Idtr;
+} PEI_S3_RESUME_STATE;
+
+#pragma pack()
+
+#define EFI_ACPI_S3_CONTEXT_GUID \
+ { \
+ 0xef98d3a, 0x3e33, 0x497a, {0xa4, 0x1, 0x77, 0xbe, 0x3e, 0xb7, 0x4f, 0x38} \
+ }
+
+extern EFI_GUID gEfiAcpiS3ContextGuid;
+
+extern EFI_GUID gEfiAcpiVariableGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/ConsoleOutDevice.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/ConsoleOutDevice.h
new file mode 100644
index 0000000000..7ca3f424e5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/ConsoleOutDevice.h
@@ -0,0 +1,23 @@
+/** @file
+ This GUID can be installed to the device handle to specify that the device is the console-out device.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __CONSOLE_OUT_DEVICE_H__
+#define __CONSOLE_OUT_DEVICE_H__
+
+#define EFI_CONSOLE_OUT_DEVICE_GUID \
+ { 0xd3b36f2c, 0xd551, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }
+
+extern EFI_GUID gEfiConsoleOutDeviceGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/MemoryTypeInformation.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/MemoryTypeInformation.h
new file mode 100644
index 0000000000..e3e2ec82fd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Guid/MemoryTypeInformation.h
@@ -0,0 +1,36 @@
+/** @file
+ This file defines:
+ * Memory Type Information GUID for HOB and Variable.
+ * Memory Type Information Variable Name.
+ * Memory Type Information GUID HOB data structure.
+
+ The memory type information HOB and variable can
+ be used to store the information for each memory type in Variable or HOB.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __MEMORY_TYPE_INFORMATION_GUID_H__
+#define __MEMORY_TYPE_INFORMATION_GUID_H__
+
+#define EFI_MEMORY_TYPE_INFORMATION_GUID \
+ { 0x4c19049f,0x4137,0x4dd3, { 0x9c,0x10,0x8b,0x97,0xa8,0x3f,0xfd,0xfa } }
+
+#define EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME L"MemoryTypeInformation"
+
+extern EFI_GUID gEfiMemoryTypeInformationGuid;
+
+typedef struct {
+ UINT32 Type; ///< EFI memory type defined in UEFI specification.
+ UINT32 NumberOfPages; ///< The pages of this type memory.
+} EFI_MEMORY_TYPE_INFORMATION;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Library/ResetSystemLib.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Library/ResetSystemLib.h
new file mode 100644
index 0000000000..6cab22a80c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Library/ResetSystemLib.h
@@ -0,0 +1,68 @@
+/** @file
+ System reset Library Services. This library class defines a set of
+ methods that reset the whole system.
+
+Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __RESET_SYSTEM_LIB_H__
+#define __RESET_SYSTEM_LIB_H__
+
+/**
+ This function causes a system-wide reset (cold reset), in which
+ all circuitry within the system returns to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ If this function returns, it means that the system does not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ );
+
+/**
+ This function causes a system-wide initialization (warm reset), in which all processors
+ are set to their initial state. Pending cycles are not corrupted.
+
+ If this function returns, it means that the system does not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ );
+
+/**
+ This function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ If this function returns, it means that the system does not support shutdown reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ );
+
+/**
+ This function causes the system to enter S3 and then wake up immediately.
+
+ If this function returns, it means that the system does not support S3 feature.
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmAccess.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmAccess.h
new file mode 100644
index 0000000000..8255a4a1d1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmAccess.h
@@ -0,0 +1,145 @@
+/** @file
+ EFI SMM Access PPI definition.
+
+ This PPI is used to control the visibility of the SMRAM on the platform.
+ It abstracts the location and characteristics of SMRAM. The expectation is
+ that the north bridge or memory controller would publish this PPI.
+
+ The principal functionality found in the memory controller includes the following:
+ - Exposing the SMRAM to all non-SMM agents, or the "open" state
+ - Shrouding the SMRAM to all but the SMM agents, or the "closed" state
+ - Preserving the system integrity, or "locking" the SMRAM, such that the settings cannot be
+ perturbed by either boot service or runtime agents
+
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMM_ACCESS_PPI_H_
+#define _SMM_ACCESS_PPI_H_
+
+#define PEI_SMM_ACCESS_PPI_GUID \
+ { 0x268f33a9, 0xcccd, 0x48be, { 0x88, 0x17, 0x86, 0x5, 0x3a, 0xc3, 0x2e, 0xd6 }}
+
+typedef struct _PEI_SMM_ACCESS_PPI PEI_SMM_ACCESS_PPI;
+
+/**
+ Opens the SMRAM area to be accessible by a PEIM driver.
+
+ This function "opens" SMRAM so that it is visible while not inside of SMM. The function should
+ return EFI_UNSUPPORTED if the hardware does not support hiding of SMRAM. The function
+ should return EFI_DEVICE_ERROR if the SMRAM configuration is locked.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This The pointer to the SMM Access Interface.
+ @param DescriptorIndex The region of SMRAM to Open.
+
+ @retval EFI_SUCCESS The region was successfully opened.
+ @retval EFI_DEVICE_ERROR The region could not be opened because locked by chipset.
+ @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_SMM_OPEN)(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN UINTN DescriptorIndex
+ );
+
+/**
+ Inhibits access to the SMRAM.
+
+ This function "closes" SMRAM so that it is not visible while outside of SMM. The function should
+ return EFI_UNSUPPORTED if the hardware does not support hiding of SMRAM.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This The pointer to the SMM Access Interface.
+ @param DescriptorIndex The region of SMRAM to Close.
+
+ @retval EFI_SUCCESS The region was successfully closed.
+ @retval EFI_DEVICE_ERROR The region could not be closed because locked by chipset.
+ @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_SMM_CLOSE)(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN UINTN DescriptorIndex
+ );
+
+/**
+ Inhibits access to the SMRAM.
+
+ This function prohibits access to the SMRAM region. This function is usually implemented such
+ that it is a write-once operation.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This The pointer to the SMM Access Interface.
+ @param DescriptorIndex The region of SMRAM to Close.
+
+ @retval EFI_SUCCESS The region was successfully locked.
+ @retval EFI_DEVICE_ERROR The region could not be locked because at least
+ one range is still open.
+ @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_SMM_LOCK)(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN UINTN DescriptorIndex
+ );
+
+/**
+ Queries the memory controller for the possible regions that will support SMRAM.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This The pointer to the SmmAccessPpi Interface.
+ @param SmramMapSize The pointer to the variable containing size of the
+ buffer to contain the description information.
+ @param SmramMap The buffer containing the data describing the Smram
+ region descriptors.
+
+ @retval EFI_BUFFER_TOO_SMALL The user did not provide a sufficient buffer.
+ @retval EFI_SUCCESS The user provided a sufficiently-sized buffer.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_SMM_CAPABILITIES)(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *This,
+ IN OUT UINTN *SmramMapSize,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+ );
+
+///
+/// EFI SMM Access PPI is used to control the visibility of the SMRAM on the platform.
+/// It abstracts the location and characteristics of SMRAM. The expectation is
+/// that the north bridge or memory controller would publish this PPI.
+///
+struct _PEI_SMM_ACCESS_PPI {
+ PEI_SMM_OPEN Open;
+ PEI_SMM_CLOSE Close;
+ PEI_SMM_LOCK Lock;
+ PEI_SMM_CAPABILITIES GetCapabilities;
+ BOOLEAN LockState;
+ BOOLEAN OpenState;
+};
+
+extern EFI_GUID gPeiSmmAccessPpiGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmControl.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmControl.h
new file mode 100644
index 0000000000..fef5a3dca3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Ppi/SmmControl.h
@@ -0,0 +1,96 @@
+/** @file
+ EFI SMM Control PPI definition.
+
+ This PPI is used to initiate SMI/PMI activations. This protocol could be published by either:
+ - A processor driver to abstract the SMI/PMI IPI
+ - The driver that abstracts the ASIC that is supporting the APM port, such as the ICH in an
+ Intel chipset
+ Because of the possibility of performing SMI or PMI IPI transactions, the ability to generate this
+ event from a platform chipset agent is an optional capability for both IA-32 and Itanium-based
+ systems.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef _SMM_CONTROL_PPI_H_
+#define _SMM_CONTROL_PPI_H_
+
+#define PEI_SMM_CONTROL_PPI_GUID \
+ { 0x61c68702, 0x4d7e, 0x4f43, 0x8d, 0xef, 0xa7, 0x43, 0x5, 0xce, 0x74, 0xc5 }
+
+typedef struct _PEI_SMM_CONTROL_PPI PEI_SMM_CONTROL_PPI;
+
+/**
+ Invokes SMI activation from either the preboot or runtime environment.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This The PEI_SMM_CONTROL_PPI instance.
+ @param ArgumentBuffer The optional sized data to pass into the protocol activation.
+ @param ArgumentBufferSize The optional size of the data.
+ @param Periodic An optional mechanism to periodically repeat activation.
+ @param ActivationInterval An optional parameter to repeat at this period one
+ time or, if the Periodic Boolean is set, periodically.
+
+ @retval EFI_SUCCESS The SMI/PMI has been engendered.
+ @retval EFI_DEVICE_ERROR The timing is unsupported.
+ @retval EFI_INVALID_PARAMETER The activation period is unsupported.
+ @retval EFI_NOT_STARTED The SMM base service has not been initialized.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_SMM_ACTIVATE) (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_CONTROL_PPI * This,
+ IN OUT INT8 *ArgumentBuffer OPTIONAL,
+ IN OUT UINTN *ArgumentBufferSize OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ );
+
+/**
+ Clears any system state that was created in response to the Active call.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This The PEI_SMM_CONTROL_PPI instance.
+ @param Periodic Optional parameter to repeat at this period one
+ time or, if the Periodic Boolean is set, periodically.
+
+ @retval EFI_SUCCESS The SMI/PMI has been engendered.
+ @retval EFI_DEVICE_ERROR The source could not be cleared.
+ @retval EFI_INVALID_PARAMETER The service did not support the Periodic input argument.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_SMM_DEACTIVATE) (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_CONTROL_PPI * This,
+ IN BOOLEAN Periodic OPTIONAL
+ );
+
+///
+/// PEI SMM Control PPI is used to initiate SMI/PMI activations. This protocol could be published by either:
+/// - A processor driver to abstract the SMI/PMI IPI
+/// - The driver that abstracts the ASIC that is supporting the APM port, such as the ICH in an
+/// Intel chipset
+///
+struct _PEI_SMM_CONTROL_PPI {
+ PEI_SMM_ACTIVATE Trigger;
+ PEI_SMM_DEACTIVATE Clear;
+};
+
+extern EFI_GUID gPeiSmmControlPpiGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Protocol/SmmVariable.h b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Protocol/SmmVariable.h
new file mode 100644
index 0000000000..7e72bee166
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/MdeModulePkg/Include/Protocol/SmmVariable.h
@@ -0,0 +1,39 @@
+/** @file
+ EFI SMM Variable Protocol is related to EDK II-specific implementation of variables
+ and intended for use as a means to store data in the EFI SMM environment.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SMM_VARIABLE_H__
+#define __SMM_VARIABLE_H__
+
+#define EFI_SMM_VARIABLE_PROTOCOL_GUID \
+ { \
+ 0xed32d533, 0x99e6, 0x4209, { 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 } \
+ }
+
+typedef struct _EFI_SMM_VARIABLE_PROTOCOL EFI_SMM_VARIABLE_PROTOCOL;
+
+///
+/// EFI SMM Variable Protocol is intended for use as a means
+/// to store data in the EFI SMM environment.
+///
+struct _EFI_SMM_VARIABLE_PROTOCOL {
+ EFI_GET_VARIABLE SmmGetVariable;
+ EFI_GET_NEXT_VARIABLE_NAME SmmGetNextVariableName;
+ EFI_SET_VARIABLE SmmSetVariable;
+ EFI_QUERY_VARIABLE_INFO SmmQueryVariableInfo;
+};
+
+extern EFI_GUID gEfiSmmVariableProtocolGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SampleCode/Pch/AcpiTables/Dsdt/PchSmb.asl b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/Pch/AcpiTables/Dsdt/PchSmb.asl
new file mode 100644
index 0000000000..25c4960585
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SampleCode/Pch/AcpiTables/Dsdt/PchSmb.asl
@@ -0,0 +1,543 @@
+/**@file
+ Provide the SMBUS ASL methods for BIOS usage.
+ Note the code requested here illegally consumes PCI IO resources and
+ collides with some runtime SMBUS driver.
+ The only valid solution is to retire this code and provide native SMBUS
+ driver with SMBUS operation region support implemented for ACPI usage.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Define various SMBus PCI Configuration Space Registers.
+//
+OperationRegion(SMBP, PCI_Config, 0x0, 0xC0)
+Field(SMBP,DWordAcc,NoLock,Preserve)
+{
+ Offset(0x20), // SMBus Base Address
+ , 5,
+ SBAR, 11,
+ Offset(0x40), // Host Configuration
+ , 2,
+ I2CE, 1, // I2C_EN
+}
+
+//
+// Define various SMBus IO Mapped Registers.
+//
+OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10)
+Field(SMBI,ByteAcc,NoLock,Preserve)
+{
+ HSTS, 8, // 0 - Host Status Register
+ Offset(0x02),
+ HCON, 8, // 2 - Host Control
+ HCOM, 8, // 3 - Host Command
+ TXSA, 8, // 4 - Transmit Slave Address
+ DAT0, 8, // 5 - Host Data 0
+ DAT1, 8, // 6 - Host Data 1
+ HBDR, 8, // 7 - Host Block Data
+ PECR, 8, // 8 - Packer Error Check
+ RXSA, 8, // 9 - Receive Slave Address
+ SDAT, 16, // A - Slave Data
+}
+
+// SMBus Send Byte - This function will write a single byte of
+// data to a specific Slave Device per SMBus Send Byte Protocol.
+// Arg0 = Address
+// Arg1 = Data
+// Return: Success = 1
+// Failure = 0
+Method(SSXB,2,Serialized)
+{
+ // Step 1: Confirm the ICHx SMBus is ready to perform
+ // communication.
+
+ If(STRT())
+ {
+ Return(0)
+ }
+
+ // Step 2: Initiate a Send Byte.
+ Store(0,I2CE) // Ensure SMbus Mode.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Arg0,TXSA) // Write Address in TXSA.
+ Store(Arg1,HCOM) // Data in HCOM.
+
+ // Set the SMBus Host control register to 0x48.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 001 = Byte Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x48,HCON)
+
+ // Step 3: Exit the Method correctly.
+ If(COMP)
+ {
+ Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others..
+ Return(1) // Return Success.
+ }
+
+ Return(0)
+}
+
+// SMBus Receive Byte - This function will write a single byte
+// of data to a specific Slave Device per SMBus Receive Byte
+// Protocol.
+// Arg0 = Address
+// Return: Success = Byte-Size Value
+// Failure = Word-Size Value = FFFFh.
+Method(SRXB,1,Serialized)
+{
+ // Step 1: Confirm the ICHx SMBus is ready to perform
+ // communication.
+ If(STRT())
+ {
+ Return(0xFFFF)
+ }
+
+ // Step 2: Initiate a Receive Byte.
+ Store(0,I2CE) // Ensure SMbus Mode.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Or(Arg0,1),TXSA) // Read Address in TXSA.
+
+ // Set the SMBus Host control register to 0x48.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 001 = Byte Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x44,HCON)
+
+ // Step 3: Exit the Method correctly.
+ If(COMP)
+ {
+ Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others
+ Return(DAT0) // Return Success.
+ }
+
+ Return(0xFFFF) // Return Failure.
+}
+
+// SMBus Write Byte - This function will write a single byte
+// of data to a specific Slave Device per SMBus Write Byte
+// Protocol.
+// Arg0 = Address
+// Arg1 = Command
+// Arg2 = Data
+// Return: Success = 1
+// Failure = 0
+Method(SWRB,3,Serialized)
+{
+ // Step 1: Confirm the ICHx SMBus is ready to perform communication.
+ If(STRT())
+ {
+ Return(0)
+ }
+
+ // Step 2: Initiate a Write Byte.
+ Store(0,I2CE) // Ensure SMbus Mode.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Arg0,TXSA) // Write Address in TXSA.
+ Store(Arg1,HCOM) // Command in HCOM.
+ Store(Arg2,DAT0) // Data in DAT0.
+
+ // Set the SMBus Host control register to 0x48.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 010 = Byte Data Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x48,HCON)
+
+ // Step 3: Exit the Method correctly.
+ If(COMP)
+ {
+ Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others..
+ Return(1) // Return Success.
+ }
+
+ Return(0) // Return Failure.
+}
+
+// SMBus Read Byte - This function will read a single byte of data
+// from a specific slave device per SMBus Read Byte Protocol.
+// Arg0 = Address
+// Arg1 = Command
+// Return: Success = Byte-Size Value
+// Failure = Word-Size Value
+Method(SRDB,2,Serialized)
+{
+ // Step 1: Confirm the ICHx SMBus is ready to perform communication.
+ If(STRT())
+ {
+ Return(0xFFFF)
+ }
+
+ // Step 2: Initiate a Read Byte.
+ Store(0,I2CE) // Ensure SMbus Mode.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Or(Arg0,1),TXSA) // Read Address in TXSA.
+ Store(Arg1,HCOM) // Command in HCOM.
+
+ // Set the SMBus Host control register to 0x48.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 010 = Byte Data Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x48,HCON)
+
+ // Step 3: Exit the Method correctly.
+ If(COMP)
+ {
+ Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others..
+ Return(DAT0) // Return Success.
+ }
+
+ Return(0xFFFF) // Return Failure.
+}
+
+// SMBus Write Word - This function will write a single word
+// of data to a specific Slave Device per SMBus Write Word
+// Protocol.
+// Arg0 = Address
+// Arg1 = Command
+// Arg2 = Data (16 bits in size)
+// Return: Success = 1
+// Failure = 0
+Method(SWRW,3,Serialized)
+{
+ // Step 1: Confirm the ICHx SMBus is ready to perform communication.
+ If(STRT())
+ {
+ Return(0)
+ }
+
+ // Step 2: Initiate a Write Word.
+ Store(0,I2CE) // Ensure SMbus Mode.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Arg0,TXSA) // Write Address in TXSA.
+ Store(Arg1,HCOM) // Command in HCOM.
+ And(Arg2,0xFF,DAT1) // Low byte Data in DAT1.
+ And(ShiftRight(Arg2,8),0xFF,DAT0) // High byte Data in DAT0.
+
+ // Set the SMBus Host control register to 0x4C.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 011 = Word Data Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x4C,HCON)
+
+ // Step 3: Exit the Method correctly.
+ If(COMP())
+ {
+ Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.
+ Return(1) // Return Success.
+ }
+
+ Return(0) // Return Failure.
+}
+
+// SMBus Read Word - This function will read a single byte of data
+// from a specific slave device per SMBus Read Word Protocol.
+// Arg0 = Address
+// Arg1 = Command
+// Return: Success = Word-Size Value
+// Failure = Dword-Size Value
+Method(SRDW,2,Serialized)
+{
+ // Step 1: Confirm the ICHx SMBus is ready to perform communication.
+ If(STRT())
+ {
+ Return(0xFFFF)
+ }
+
+ // Step 2: Initiate a Read Word.
+ Store(0,I2CE) // Ensure SMbus Mode.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Or(Arg0,1),TXSA) // Read Address in TXSA.
+ Store(Arg1,HCOM) // Command in HCOM.
+
+ // Set the SMBus Host control register to 0x4C.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 011 = Word Data Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x4C,HCON)
+
+ // Step 3: Exit the Method correctly.
+ If(COMP())
+ {
+ Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.
+ Return(Or(ShiftLeft(DAT0,8),DAT1)) // Return Success.
+ }
+
+ Return(0xFFFFFFFF) // Return Failure.
+}
+
+// SMBus Block Write - This function will write an entire block of data
+// to a specific slave device per SMBus Block Write Protocol.
+// Arg0 = Address
+// Arg1 = Command
+// Arg2 = Buffer of Data to Write
+// Arg3 = 1 = I2C Block Write, 0 = SMBus Block Write
+// Return: Success = 1
+// Failure = 0
+Method(SBLW,4,Serialized)
+{
+ // Step 1: Confirm the ICHx SMBus is ready to perform communication.
+ If(STRT())
+ {
+ Return(0)
+ }
+
+ // Step 2: Initiate a Block Write.
+ Store(Arg3,I2CE) // Select the proper protocol.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Arg0,TXSA) // Write Address in TXSA.
+ Store(Arg1,HCOM) // Command in HCOM.
+ Store(Sizeof(Arg2),DAT0) // Count in DAT0.
+ Store(0,Local1) // Init Pointer to Buffer.
+ Store(DerefOf(Index(Arg2,0)),HBDR) // First Byte in HBD Register.
+
+ // Set the SMBus Host control register to 0x48.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 101 = Block Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x54,HCON)
+
+ // Step 3: Send the entire Block of Data.
+ While(LGreater(Sizeof(Arg2),Local1))
+ {
+ // Wait up to 200ms for Host Status to get set.
+ Store(4000,Local0) // 4000 * 50us = 200ms.
+
+ While(LAnd(LNot(And(HSTS,0x80)),Local0))
+ {
+ Decrement(Local0) // Decrement Count.
+ Stall(50) // Delay = 50us.
+ }
+
+ If(LNot(Local0)) // Timeout?
+ {
+ KILL() // Yes. Kill Communication.
+ Return(0) // Return failure.
+ }
+
+ Store(0x80,HSTS) // Clear Host Status.
+ Increment(Local1) // Point to Next Byte.
+
+ // Place next byte in HBDR if last byte has not been sent.
+ If(LGreater(Sizeof(Arg2),Local1))
+ {
+ Store(DerefOf(Index(Arg2,Local1)),HBDR)
+ }
+ }
+
+ // Step 4: Exit the Method correctly.
+ If(COMP())
+ {
+ Or(HSTS,0xFF,HSTS) // Clear all status bits.
+ Return(1) // Return Success.
+ }
+
+ Return(0) // Return Failure.
+}
+
+// SMBus Block Read - This function will read a block of data from
+// a specific slave device per SMBus Block Read Protocol.
+// Arg0 = Address
+// Arg1 = Command
+// Arg2 = 1 = I2C Block Write, 0 = SMBus Block Write
+// Return: Success = Data Buffer (First Byte = length)
+// Failure = 0
+Method(SBLR,3,Serialized)
+{
+ Name(TBUF, Buffer(256) {})
+
+ // Step 1: Confirm the ICHx SMBus is ready to perform communication.
+ If(STRT())
+ {
+ Return(0)
+ }
+
+ // Step 2: Initiate a Block Read.
+ Store(Arg2,I2CE) // Select the proper protocol.
+ Store(0xBF,HSTS) // Clear all but INUSE_STS.
+ Store(Or(Arg0,1),TXSA) // Read Address in TXSA.
+ Store(Arg1,HCOM) // Command in HCOM.
+
+ // Set the SMBus Host control register to 0x48.
+ // Bit 7: = 0 = reserved
+ // Bit 6: = 1 = start
+ // Bit 5: = 0 = disregard, I2C related bit
+ // Bits 4:2: = 101 = Block Protocol
+ // Bit 1: = 0 = Normal Function
+ // Bit 0: = 0 = Disable interrupt generation
+ Store(0x54,HCON)
+
+ // Step 3: Wait up to 200ms to get the Data Count.
+ Store(4000,Local0) // 4000 * 50us = 200ms.
+
+ While(LAnd(LNot(And(HSTS,0x80)),Local0))
+ {
+ Decrement(Local0) // Decrement Count.
+ Stall(50) // Delay = 50us.
+ }
+
+ If(LNot(Local0)) // Timeout?
+ {
+ KILL() // Yes. Kill Communication.
+ Return(0) // Return failure.
+ }
+
+ Store(DAT0,Index(TBUF,0)) // Get the Data Count.
+ Store(0x80,HSTS) // Clear Host Status.
+ Store(1,Local1) // Local1 = Buffer Pointer.
+
+ // Step 4: Get the Block Data and store it.
+ While(LLess(Local1,DerefOf(Index(TBUF,0))))
+ {
+ // Wait up to 200ms for Host Status to get set.
+ Store(4000,Local0) // 4000 * 50us = 200ms.
+
+ While(LAnd(LNot(And(HSTS,0x80)),Local0))
+ {
+ Decrement(Local0) // Decrement Count.
+ Stall(50) // Delay = 50us.
+ }
+
+ If(LNot(Local0)) // Timeout?
+ {
+ KILL() // Yes. Kill Communication.
+ Return(0) // Return failure.
+ }
+
+ Store(HBDR,Index(TBUF,Local1)) // Place into Buffer.
+ Store(0x80,HSTS) // Clear Host Status.
+ Increment(Local1)
+ }
+
+ // Step 5: Exit the Method correctly.
+ If(COMP())
+ {
+ Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.
+ Return(TBUF) // Return Success.
+ }
+
+ Return(0) // Return Failure.
+}
+
+
+// SMBus Start Check
+// Return: Success = 0
+// Failure = 1
+Method(STRT,0,Serialized)
+{
+ // Wait up to 200ms to confirm the SMBus Semaphore has been
+ // released (In Use Status = 0). Note that the Sleep time may take
+ // longer as the This function will yield the Processor such that it
+ // may perform different tasks during the delay.
+ Store(200,Local0) // 200 * 1ms = 200ms.
+
+ While(Local0)
+ {
+ If(And(HSTS,0x40)) // In Use Set?
+ {
+ Decrement(Local0) // Yes. Decrement Count.
+ Sleep(1) // Delay = 1ms.
+ If(LEqual(Local0,0)) // Count = 0?
+ {
+ Return(1) // Return failure.
+ }
+ }
+ Else
+ {
+ Store(0,Local0) // In Use Clear. Continue.
+ }
+ }
+
+ // In Use Status = 0 during last read, which will make subsequent
+ // reads return In Use Status = 1 until software clears it. All
+ // software using ICHx SMBus should check this bit before initiating
+ // any SMBus communication.
+
+ // Wait up to 200ms to confirm the Host Interface is
+ // not processing a command.
+ Store(4000,Local0) // 4000 * 50us = 200ms.
+
+ While(Local0)
+ {
+ If(And(HSTS,0x01)) // Host Busy Set?
+ {
+ Decrement(Local0) // Decrement Count.
+ Stall(50) // Delay = 50us.
+ If(LEqual(Local0,0)) // Count = 0?
+ {
+ KILL() // Yes. Kill Communication.
+ }
+ }
+ Else
+ {
+ Return(0)
+ }
+ }
+
+ Return(1) // Timeout. Return failure.
+}
+
+// SMBus Completion Check
+// Return: Success = 1
+// Failure = 0
+Method(COMP,0,Serialized)
+{
+ // Wait for up to 200ms for the Completion Command
+ // Status to get set.
+ Store(4000,Local0) // 4000 * 50us = 200ms.
+
+ While(Local0)
+ {
+ If(And(HSTS,0x02)) // Completion Status Set?
+ {
+ Return(1) // Yes. We are done.
+ }
+ Else
+ {
+ Decrement(Local0) // Decrement Count.
+ Stall(50) // Delay 50us.
+ If(LEqual(Local0,0)) // Count = 0?
+ {
+ KILL() // Yes. Kill Communication.
+ }
+ }
+ }
+
+ Return(0) // Timeout. Return Failure.
+}
+
+// SMBus Kill Command
+Method(KILL,0,Serialized)
+{
+ Or(HCON,0x02,HCON) // Yes. Send Kill command.
+ Or(HSTS,0xFF,HSTS) // Clear all status.
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SiPkg.dec b/Silicon/Intel/KabylakeSiliconPkg/SiPkg.dec
new file mode 100644
index 0000000000..92b6d492ee
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SiPkg.dec
@@ -0,0 +1,628 @@
+## @file
+# Component description file for the Silicon Reference Code.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+DEC_SPECIFICATION = 0x00010017
+PACKAGE_NAME = SiPkg
+PACKAGE_VERSION = 0.1
+PACKAGE_GUID = F245E276-44A0-46b3-AEB5-9898BBCF008D
+
+
+[Includes]
+Include
+SampleCode/Include
+SampleCode/MdeModulePkg/Include
+SampleCode/IntelFrameworkPkg/Include
+#
+# SystemAgent
+#
+SystemAgent/Include
+SystemAgent/MemoryInit/Include
+SystemAgent/AcpiTables
+#
+# Cpu
+#
+Cpu/Include
+#
+# Me
+#
+Me/Include
+#
+# Pch
+#
+Pch/Include
+Pch/AcpiTables/Dsdt
+
+[Includes.Common.Private]
+IncludePrivate
+#
+# Cpu
+#
+Cpu/IncludePrivate
+#
+# Pch
+#
+Pch/IncludePrivate
+#
+# SystemAgent
+#
+SystemAgent/IncludePrivate
+
+[Guids]
+##
+## MdeModulePkg
+##
+gEfiMemoryTypeInformationGuid = {0x4c19049f, 0x4137, 0x4dd3, {0x9c, 0x10, 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa}}
+gEfiCapsuleVendorGuid = {0x711c703f, 0xc285, 0x4b10, {0xa3, 0xb0, 0x36, 0xec, 0xbd, 0x3c, 0x8b, 0xe2}}
+gEfiConsoleOutDeviceGuid = {0xd3b36f2c, 0xd551, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d}}
+##
+## IntelFrameworkPkg
+##
+gEfiSmmPeiSmramMemoryReserveGuid = {0x6dadf1d1, 0xd4cc, 0x4910, {0xbb, 0x6e, 0x82, 0xb1, 0xfd, 0x80, 0xff, 0x3d}}
+##
+##
+##
+gSmbiosProcessorInfoHobGuid = {0xe6d73d92, 0xff56, 0x4146, {0xaf, 0xac, 0x1c, 0x18, 0x81, 0x7d, 0x68, 0x71}}
+gSmbiosCacheInfoHobGuid = {0xd805b74e, 0x1460, 0x4755, {0xbb, 0x36, 0x1e, 0x8c, 0x8a, 0xd6, 0x78, 0xd7}}
+##
+## Common
+##
+gSiConfigGuid = {0x4ed6d282, 0x22f3, 0x4fe1, {0xa6, 0x61, 0x6, 0x1a, 0x97, 0x38, 0x59, 0xd8}}
+gSiPkgTokenSpaceGuid = {0x977c97c1, 0x47e1, 0x4b6b, {0x96, 0x69, 0x43, 0x66, 0x99, 0xcb, 0xe4, 0x5b}}
+##
+## SystemAgent
+##
+
+gSaAcpiTableStorageGuid = {0x3c0ed5e2, 0x91ea, 0x4b94, {0x82, 0xd, 0x9d, 0xaf, 0x9a, 0x3b, 0xb4, 0xa2}}
+gSaConfigHobGuid = {0x762fa2e6, 0xea3b, 0x41c8, {0x8c, 0x52, 0x63, 0x76, 0x6d, 0x70, 0x39, 0xe0}}
+gVtdConfigGuid = {0x03e5cf63, 0xbebb, 0x4041, {0xb7, 0xe7, 0xbf, 0x54, 0x61, 0x20, 0xf1, 0xc5}}
+gMiscDxeConfigGuid = {0x7ce5f5ef, 0x4ef1, 0x4f9f, {0x8e, 0x29, 0x5f, 0xf4, 0x5f, 0x2f, 0xd8, 0xaf}}
+gSaSsdtAcpiTableStorageGuid = {0xca89914d, 0x2317, 0x452e, {0xb2, 0x45, 0x36, 0xc6, 0xfb, 0x77, 0xa9, 0xc6}}
+gSaMiscPeiPreMemConfigGuid = {0x4a525577, 0x3469, 0x4f11, {0x99, 0xcf, 0xfb, 0xcd, 0x5e, 0xf1, 0x84, 0xe4}}
+gMemoryConfigGuid = {0x26cf084c, 0xc9db, 0x41bb, {0x92, 0xc6, 0xd1, 0x97, 0xb8, 0xa1, 0xe4, 0xbf}}
+gMemoryConfigNoCrcGuid = {0xc56c73d0, 0x1cdb, 0x4c0c, {0xa9, 0x57, 0xea, 0x62, 0xa9, 0xe6, 0xf5, 0x0c}}
+gGraphicsPeiConfigGuid = {0x04249ac0, 0x0088, 0x439f, {0xa7, 0x4e, 0xa7, 0x04, 0x2a, 0x06, 0x2f, 0x5d}}
+gGraphicsDxeConfigGuid = {0x34d93161, 0xf78e, 0x4915, {0xad, 0xc4, 0xdb, 0x67, 0x16, 0x42, 0x39, 0x24}}
+gFspReservedMemoryResourceHobTsegGuid = {0xd038747c, 0xd00c, 0x4980, {0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55}}
+## Include/Guid/AcpiS3Context.h
+gEfiAcpiVariableGuid = {0xaf9ffd67, 0xec10, 0x488a, {0x9d, 0xfc, 0x6c, 0xbf, 0x5e, 0xe2, 0x2c, 0x2e}}
+## IntelFsp2Pkg/IntelFsp2Pkg.dec gSiMemoryS3DataGuid is the same as gFspNonVolatileStorageHobGuid
+gSiMemoryS3DataGuid = {0x721acf02, 0x4d77, 0x4c2a, {0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0}}
+gSiMemoryInfoDataGuid = {0x9b2071d4, 0xb054, 0x4e0c, {0x8d, 0x09, 0x11, 0xcf, 0x8b, 0x9f, 0x03, 0x23}}
+gSiMemoryPlatformDataGuid = {0x6210d62f, 0x418d, 0x4999, {0xa2, 0x45, 0x22, 0x10, 0x0a, 0x5d, 0xea, 0x44}}
+## Include/MrcRmtData.h
+gEfiMemorySchemaGuid = {0xCE3F6794, 0x4883, 0x492C, {0x8D, 0xBA, 0x2F, 0xC0, 0x98, 0x44, 0x77, 0x10}}
+gMrcSchemaListHobGuid = {0x3047C2AC, 0x5E8E, 0x4C55, {0xA1, 0xCB, 0xEA, 0xAD, 0x0A, 0x88, 0x86, 0x1B}}
+## Include/SsaCommonConfig.h
+gSsaPostcodeHookGuid = {0xADF0A27B, 0x61A6, 0x4F18, {0x9E, 0xAC, 0x46, 0x87, 0xE7, 0x9E, 0x6F, 0xBB}}
+gSsaBiosVariablesGuid = {0x43eeffe8, 0xa978, 0x41dc, {0x9d, 0xb6, 0x54, 0xc4, 0x27, 0xf2, 0x7e, 0x2a}}
+gSsaBiosResultsGuid = {0x8f4e928, 0xf5f, 0x46d4, {0x84, 0x10, 0x47, 0x9f, 0xda, 0x27, 0x9d, 0xb6}}
+##
+## Cpu
+##
+gSmramCpuDataHeaderGuid = {0x5848fd2d, 0xd6af, 0x474b, {0x82, 0x75, 0x95, 0xdd, 0xe7, 0x0a, 0xe8, 0x23}}
+gCpuAcpiTableStorageGuid = {0xc38fb0e2, 0x0c43, 0x49c9, {0xb5, 0x44, 0x9b, 0x17, 0xaa, 0x4d, 0xcb, 0xa3}}
+gTxtInfoHobGuid = {0x2986883f, 0x88e0, 0x48d0, {0x4b, 0x82, 0x20, 0xc2, 0x69, 0x48, 0xdd, 0xac}}
+gHtBistHobGuid = {0xbe644001, 0xe7d4, 0x48b1, {0xb0, 0x96, 0x8b, 0xa0, 0x47, 0xbc, 0x7a, 0xe7}}
+gProcessorProducerGuid = {0x1bf06aea, 0x5bec, 0x4a8d, {0x95, 0x76, 0x74, 0x9b, 0x09, 0x56, 0x2d, 0x30}}
+gCpuInitDataHobGuid = {0x266e31cc, 0x13c5, 0x4807, {0xb9, 0xdc, 0x39, 0xa6, 0xba, 0x88, 0xff, 0x1a}}
+gCpuS3ResumeDataHobGuid = {0x3972d4c1, 0xf206, 0x463f, {0x80, 0xa4, 0xd9, 0x62, 0x79, 0x0a, 0xe5, 0x49}}
+gBiosGuardHobGuid = {0x66f0c42d, 0x0d0e, 0x4c23, {0x93, 0xc0, 0x2d, 0x52, 0x95, 0xdc, 0x5e, 0x21}}
+gCpuSecurityPreMemConfigGuid = {0x371d96b3, 0x4b33, 0x4e6d, {0xac, 0x1e, 0xf2, 0xbf, 0x65, 0x84, 0xf1, 0xfe}}
+gCpuConfigLibPreMemConfigGuid = {0xa6fbf224, 0x1bf6, 0x4b24, {0x83, 0x79, 0xcc, 0x4e, 0x40, 0x6f, 0x22, 0x46}}
+gCpuTxtPreMemConfigGuid = {0x4debe24d, 0x53c9, 0x4777, {0xaf, 0x28, 0xf, 0x21, 0xd9, 0x28, 0x35, 0xe5}}
+gCpuSgxConfigGuid = {0xc4ea0516, 0x3f6f, 0x4136, {0x93, 0x64, 0xf3, 0x36, 0xf2, 0xb1, 0xa6, 0xe9}}
+gCpuTestConfigGuid = {0x6bcd6887, 0x2fa6, 0x4e28, {0xba, 0x40, 0x69, 0x3e, 0xed, 0x31, 0x94, 0x79}}
+gBiosGuardConfigGuid = {0xaae1a623, 0xde54, 0x4a03, {0xab, 0x10, 0x9f, 0x80, 0x8d, 0x9c, 0x40, 0xa1}}
+gCpuConfigGuid = {0xaab70e04, 0x4358, 0x46be, {0xba, 0x2c, 0xbf, 0x2f, 0x54, 0x7b, 0xd9, 0xc4}}
+gCpuOverclockingPreMemConfigGuid = {0xb8f29b80, 0x6de3, 0x42ff, {0xae, 0xcd, 0x59, 0xd9, 0x98, 0xc, 0x9, 0x7b}}
+gCpuPidTestConfigGuid = {0xa15c988f, 0xbb10, 0x4f55, {0x82, 0x84, 0xea, 0xe3, 0x2b, 0x8e, 0xeb, 0x40}}
+gCpuPowerMgmtBasicConfigGuid = {0xbd674f09, 0x434, 0x4e46, {0xbd, 0xf9, 0x22, 0x4d, 0x7, 0xbb, 0x3f, 0x6}}
+gCpuPowerMgmtCustomConfigGuid = {0x33a6f481, 0xfd, 0x47ed, {0x99, 0xe6, 0x1b, 0x9f, 0x57, 0x27, 0xb5, 0x36}}
+gCpuPowerMgmtPsysConfigGuid = {0xcea87a5, 0xe257, 0x4ca9, {0xae, 0xc4, 0x69, 0x56, 0xf3, 0x9, 0x99, 0x56}}
+gCpuPowerMgmtTestConfigGuid = {0x8a0fcb5f, 0x3890, 0x40b8, {0x82, 0xd, 0xbb, 0x3, 0xd7, 0x13, 0xf2, 0x32}}
+gCpuPowerMgmtVrConfigGuid = {0x75f14a61, 0xe01, 0x4402, {0x93, 0x5, 0xf, 0x74, 0xa9, 0x60, 0x7d, 0x87}}
+##
+## Me
+##
+gAmtForcePushPetPolicyGuid = {0xacc8e1e4, 0x9f9f, 0x4e40, {0xa5, 0x7e, 0xf9, 0x9e, 0x52, 0xf3, 0x4c, 0xa5}}
+gAmtForcePushPetVariableGuid = {0xd7ac94af, 0xa498, 0x45ec, {0xbf, 0xa2, 0xa5, 0x6e, 0x95, 0x34, 0x61, 0x8b}}
+gConsoleLockGuid = {0x368cda0d, 0xcf31, 0x4b9b, {0x8c, 0xf6, 0xe7, 0xd1, 0xbf, 0xff, 0x15, 0x7e}}
+gMeBiosExtensionSetupGuid = {0xaf013532, 0xc828, 0x4fbd, {0x20, 0xae, 0xfe, 0xe6, 0xaf, 0xbe, 0xdd, 0x4e}}
+gMePlatformReadyToBootGuid = {0x03fdf171, 0x1d67, 0x4ace, {0xa9, 0x04, 0x3e, 0x36, 0xd3, 0x38, 0xfa, 0x74}}
+gAlertAtHandlerGuid = {0xb441df87, 0x8d94, 0x4811, {0x85, 0xf7, 0x0f, 0x9a, 0x7b, 0xf8, 0x9d, 0x2a}}
+gMeSsdtAcpiTableStorageGuid = {0x9a8f82d5, 0x39b1, 0x48da, {0x92, 0xdc, 0xa2, 0x2d, 0xa8, 0x83, 0x4d, 0xf6}}
+gAmtPetQueueHobGuid = {0xca0801d3, 0xafb1, 0x4dec, {0x9b, 0x65, 0x93, 0x65, 0xec, 0xc7, 0x93, 0x6b}}
+gAmtForcePushPetHobGuid = {0x4efa0db6, 0x26dc, 0x4bb1, {0xa7, 0x6f, 0x14, 0xbc, 0x63, 0x0c, 0x7b, 0x3c}}
+gMeDataHobGuid = {0x1e94f097, 0x5acd, 0x4089, {0xb2, 0xe3, 0xb9, 0xa5, 0xc8, 0x79, 0xa7, 0x0c}}
+gTpm2AcpiTableStorageGuid = {0x7d279373, 0xeecc, 0x4d4f, {0xae, 0x2f, 0xce, 0xc4, 0xb7, 0x06, 0xb0, 0x6a}}
+gMeBiosPayloadHobGuid = {0x992c52c8, 0xbc01, 0x4ecd, {0x20, 0xbf, 0xf9, 0x57, 0x16, 0x0e, 0x9e, 0xf7}}
+gEfiTouchPanelGuid = {0x91b1d27b, 0xe126, 0x48d1, {0x82, 0x34, 0xd2, 0x8b, 0x81, 0xc8, 0x83, 0x62}}
+gMeFwHobGuid = {0x52885e62, 0x4c4d, 0x9546, {0x2d, 0xba, 0x2a, 0x84, 0x89, 0xee, 0xa8, 0xa3 }}
+gMePeiPreMemConfigGuid = {0x67ed113b, 0xd4ab, 0x43f5, {0x9c, 0x3c, 0x35, 0x44, 0x15, 0xaa, 0x47, 0x5c}}
+gMePeiConfigGuid = {0x9bad5628, 0x657b, 0x48e3, {0xb1, 0x11, 0xc3, 0xb9, 0xeb, 0xea, 0xee, 0x17}}
+gMeDxeConfigGuid = {0xad08bacc, 0x4906, 0x4d9b, {0xbe, 0xd1, 0x81, 0xa5, 0x2c, 0x13, 0xdb, 0xf8}}
+gAmtPeiConfigGuid = {0x7254546a, 0xace3, 0x4a32, {0x9a, 0xc2, 0xf0, 0xcc, 0x28, 0x4e, 0x1e, 0x4d}}
+gAmtDxeConfigGuid = {0x3f12ab6b, 0xb04d, 0x4824, {0xbf, 0xb6, 0x3e, 0xe7, 0x5d, 0x02, 0x0b, 0x84}}
+gIvmProtocolGuid = {0x3C4852D6, 0xD47B, 0x4F46, {0xB0, 0x5E, 0xB5, 0xED, 0xC1, 0xAA, 0x44, 0x0E}}
+gSdmProtocolGuid = {0xDBA4D603, 0xD7ED, 0x4931, {0x88, 0x23, 0x17, 0xAD, 0x58, 0x57, 0x05, 0xD5}}
+gRtmProtocolGuid = {0x5565A099, 0x7FE2, 0x45C1, {0xA2, 0x2B, 0xD7, 0xE9, 0xDF, 0xEA, 0x9A, 0x2E}}
+gSvmProtocolGuid = {0xF47ACC04, 0xD94B, 0x49CA, {0x87, 0xA6, 0x7F, 0x7D, 0xC0, 0x3F, 0xBA, 0xF3}}
+gMeEopDoneHobGuid = {0x247323af, 0xc8f1, 0x4b8c, {0x90, 0x87, 0xaa, 0x4b, 0xa7, 0xb7, 0x6d, 0x6a}}
+gMePreMemPolicyHobGuid = {0xe6de74a5, 0x21b, 0x4f78, {0xa3, 0xcd, 0x34, 0xd6, 0x7e, 0xe4, 0x82, 0xbf}}
+gMePolicyHobGuid = {0x0341cf17, 0xbc8f, 0x4a20, {0xac, 0x28, 0x6c, 0x3c, 0x32, 0x4c, 0xd4, 0x17}}
+gAmtPolicyHobGuid = {0x703eb2cd, 0x5ca8, 0x4233, {0x9d, 0xa3, 0x0d, 0x2d, 0x57, 0xe6, 0x73, 0x34}}
+
+##
+## PCH
+##
+gEfiSmbusArpMapGuid = {0x707be83e, 0x0bf6, 0x40a5, {0xbe, 0x64, 0x34, 0xc0, 0x3a, 0xa0, 0xb8, 0xe2}}
+gIrmtAcpiTableStorageGuid = {0x6684d675, 0xee06, 0x49b2, {0x87, 0x6f, 0x79, 0xc5, 0x8f, 0xdd, 0xa5, 0xb7}}
+gPchGlobalResetGuid = { 0x9db31b4c, 0xf5ef, 0x48bb, { 0x94, 0x2b, 0x18, 0x1f, 0x7e, 0x3a, 0x3e, 0x40 }}
+gI2c0MasterGuid = {0xa121a5db, 0xb0cb, 0x46ec, {0xa0, 0xcb, 0x27, 0xf8, 0xda, 0x72, 0xd4, 0x0e}}
+gI2c1MasterGuid = {0x55e3d0f9, 0xc954, 0x422d, {0x9c, 0x4c, 0xcc, 0x46, 0x12, 0x7c, 0x5b, 0xa8}}
+gI2c2MasterGuid = {0x9289aa40, 0xdf32, 0x474e, {0xb0, 0x3a, 0xc7, 0x7f, 0x76, 0xd3, 0x45, 0x21}}
+gI2c3MasterGuid = {0xd8b2c17f, 0x4117, 0x4166, {0x90, 0x17, 0x01, 0x68, 0xb4, 0x81, 0xac, 0x18}}
+gI2c4MasterGuid = {0x513d943d, 0x15d9, 0x4bd0, {0xb1, 0x41, 0x14, 0x50, 0x2b, 0xbf, 0xa9, 0xf2}}
+gI2c5MasterGuid = {0x50df382a, 0xb6bf, 0x4435, {0xae, 0xe6, 0x21, 0xf4, 0x85, 0x7c, 0xa8, 0xb4}}
+gChipsetInitHobGuid = { 0xc1392859, 0x1f65, 0x446e, { 0xb3, 0xf5, 0x84, 0x35, 0xfc, 0xc7, 0xd1, 0xc4 }}
+
+gPchGeneralPreMemConfigGuid = {0xC65F62FA, 0x52B9, 0x4837, {0x86, 0xEB, 0x1A, 0xFB, 0xD4, 0xAD, 0xBB, 0x3E}}
+gDciPreMemConfigGuid = {0xAB4AF366, 0x2250, 0x40C3, {0x92, 0xDB, 0x36, 0x61, 0xC6, 0x71, 0x3C, 0x5A}}
+gWatchDogPreMemConfigGuid = {0xFBCE08CC, 0x60F2, 0x4BDF, {0xB7, 0x88, 0x09, 0xBB, 0x81, 0x65, 0x52, 0x2B}}
+gTraceHubPreMemConfigGuid = {0xC26AC3F6, 0xDAD0, 0x4E91, {0xB6, 0xD6, 0xD8, 0x51, 0x6F, 0x8F, 0x9B, 0x7B}}
+gPcieRpPreMemConfigGuid = {0x8377AB38, 0xF8B0, 0x476A, { 0x9C, 0xA1, 0x68, 0xEA, 0x78, 0x57, 0xD8, 0x2A}}
+gHpetPreMemConfigGuid = {0x7C75C0F1, 0xA20F, 0x42EB, {0x83, 0xDE, 0xE8, 0x58, 0xAB, 0x81, 0xC5, 0xDC}}
+gSmbusPreMemConfigGuid = {0x77A6E62C, 0x716B, 0x4386, {0x9E, 0x9C, 0x23, 0xA0, 0x2E, 0x13, 0x7B, 0x3A}}
+gLpcPreMemConfigGuid = {0xA6E6032F, 0x1E58, 0x407E, {0x9A, 0xB8, 0xC6, 0x30, 0xC6, 0xC4, 0x11, 0x8E}}
+gHsioPciePreMemConfigGuid = {0xE8FB0C12, 0x0DA1, 0x4A20, {0xB3, 0x36, 0xFB, 0x75, 0x93, 0x8C, 0xE0, 0x14}}
+gHsioSataPreMemConfigGuid = {0x732260D0, 0xA5C1, 0x4119, {0xAA, 0x0C, 0x93, 0xDC, 0xAC, 0x67, 0x0A, 0x31}}
+gHsioPreMemConfigGuid = {0xbc9e5787, 0x3ddb, 0x4916, {0x8c, 0xcc, 0x82, 0xb8, 0x9, 0x43, 0xe2, 0xf0}}
+
+gPchGeneralConfigGuid = {0x6ED94C8C, 0x25F7, 0x4686, {0xB2, 0x46, 0xCA, 0x4D, 0xE2, 0x95, 0x4B, 0x5D}}
+gPcieRpConfigGuid = {0x0A53B507, 0x988B, 0x475C, {0xBF, 0x76, 0x33, 0xDE, 0x10, 0x6D, 0x94, 0x84}}
+gSataConfigGuid = {0xF5F87B4F, 0xCC3C, 0x408D, {0x89, 0xE3, 0x61, 0xC5, 0x9C, 0x54, 0x07, 0xC4}}
+gIoApicConfigGuid = {0x2873D0F1, 0x00F6, 0x40AB, {0xAC, 0x36, 0x9A, 0x68, 0xBA, 0x87, 0x3E, 0x6C}}
+gCio2ConfigGuid = {0xFBC4C192, 0x789D, 0x4038, {0x90, 0xE1, 0x5E, 0x6D, 0xFD, 0x52, 0xAF, 0x8A}}
+gDmiConfigGuid = {0xB3A61210, 0x1CD3, 0x4797, {0x8E, 0xE6, 0xD3, 0x42, 0x9C, 0x4F, 0x17, 0xBD}}
+gFlashProtectionConfigGuid = {0xD0F71512, 0x9E32, 0x4CC9, {0xA5, 0xA3, 0xAD, 0x67, 0x9A, 0x06, 0x67, 0xB8}}
+gHdAudioConfigGuid = {0x7EB3CE7E, 0x82E0, 0x4CD7, {0xBD, 0xE5, 0xB2, 0xBF, 0x4E, 0x91, 0xC3, 0x4C}}
+gInterruptConfigGuid = {0x09A2B815, 0xBE29, 0x45EF, {0xBF, 0xBF, 0x58, 0xEA, 0xAC, 0x5E, 0x29, 0x78}}
+gIshConfigGuid = {0x433AE2AA, 0xC5A6, 0x46ED, {0x94, 0x19, 0x1E, 0x5D, 0xB8, 0x1C, 0x57, 0x40}}
+gLanConfigGuid = {0x4B2DE99E, 0x7517, 0x4D04, {0x8C, 0x02, 0xF1, 0x1A, 0x59, 0x2B, 0x14, 0x2F}}
+gLockDownConfigGuid = {0x8A838E0A, 0xA639, 0x46F0, {0xA9, 0xCE, 0x70, 0xC4, 0x85, 0xFB, 0xA8, 0x0D}}
+gP2sbConfigGuid = {0x2474DCB8, 0x4BB4, 0x49DA, {0x87, 0x83, 0x7C, 0xD3, 0xD3, 0x85, 0xFF, 0x07}}
+gPmConfigGuid = {0x93826157, 0xDC85, 0x4E34, {0xAE, 0xD9, 0x6E, 0xA1, 0x0D, 0xF9, 0xE3, 0xA7}}
+gPort61ConfigGuid = {0x59913475, 0x1960, 0x4099, {0x80, 0xEC, 0xAF, 0xC7, 0xCF, 0x5F, 0x9F, 0xAC}}
+gScsConfigGuid = {0xF4DE6D52, 0xB5C9, 0x48C0, {0xA0, 0x4A, 0x68, 0x54, 0x20, 0x94, 0x05, 0xD0}}
+gSerialIoConfigGuid = {0x6CC06EBF, 0x0D34, 0x4340, {0xBC, 0x16, 0xDA, 0x09, 0xE5, 0x78, 0x3A, 0xDB}}
+gSerialIrqConfigGuid = {0x251701E7, 0xE266, 0x4623, {0x99, 0x68, 0x73, 0x8C, 0xD2, 0x23, 0x10, 0x96}}
+gSpiConfigGuid = {0x150360EF, 0x99BE, 0x4E43, {0x94, 0xBB, 0xBD, 0x40, 0x26, 0xCA, 0x34, 0x57}}
+gEspiConfigGuid = {0x398D5D32, 0x2285, 0x4207, {0x80, 0xA2, 0xD4, 0x49, 0xBD, 0x9C, 0x79, 0x93}}
+gThermalConfigGuid = {0x4416506D, 0x1197, 0x4722, {0xA5, 0xB4, 0x46, 0x11, 0xF9, 0x23, 0x9E, 0xAE}}
+gUsbConfigGuid = {0xB2DA9CCD, 0x6A8C, 0x4BB6, {0xB3, 0xE6, 0xCD, 0xFB, 0xB7, 0x66, 0x8B, 0xDE}}
+gPchPcieStorageDetectHobGuid = {0xC682F3F4, 0x2F46, 0x495E, {0x98, 0xAA, 0x43, 0x14, 0x4B, 0xA5, 0xA4, 0x85}}
+
+
+##
+## SecurityPkg
+##
+## GUID used to "Tcg2PhysicalPresence" variable and "Tcg2PhysicalPresenceFlags" variable for TPM2 request and response.
+# Include/Guid/Tcg2PhysicalPresenceData.h
+gEfiTcg2PhysicalPresenceGuid = { 0xaeb9c5c1, 0x94f1, 0x4d02, { 0xbf, 0xd9, 0x46, 0x2, 0xdb, 0x2d, 0x3c, 0x54 }}
+gTpmDeviceInstanceTpm20PttGuid = {0x72cd3a7b, 0xfea5, 0x4f5e, {0x91, 0x65, 0x4d, 0xd1, 0x21, 0x87, 0xbb, 0x13}}
+gTpmDeviceInstanceTpm20PttPtpGuid = {0x93d66f66, 0x55da, 0x4f03, {0x9b, 0x5f, 0x32, 0xcf, 0x9e, 0x54, 0x3b, 0x3a}}
+gEfiTrEEPhysicalPresenceGuid = {0xf24643c2, 0xc622, 0x494e, {0x8a, 0x0d, 0x46, 0x32, 0x57, 0x9c, 0x2d, 0x5b}}
+gTcoWdtHobGuid = { 0x3e405418, 0x0d8c, 0x4f1a, { 0xb0, 0x55, 0xbe, 0xf9, 0x08, 0x41, 0x46, 0x8d }}
+
+##
+## PreMem Performance
+##
+gPerfPchPrePolicyGuid = {0x3112356F, 0xCC77, 0x4E82, {0x86, 0xD5, 0x3E, 0x25, 0xEE, 0x81, 0x92, 0xA4}}
+gPerfSiValidateGuid = {0x681F96E6, 0xF9CF, 0x464D, {0x97, 0x9A, 0xB1, 0x11, 0x33, 0xDE, 0x37, 0xA9}}
+gPerfPchValidateGuid = {0xD0FF37D6, 0xA569, 0x4058, {0xB3, 0xDA, 0x29, 0x0B, 0x38, 0xC5, 0x32, 0x25}}
+gPerfAmtValidateGuid = {0x9E949422, 0x4A7A, 0x4E41, {0xB0, 0xAB, 0x3C, 0x0D, 0x88, 0x0A, 0x00, 0xFF}}
+gPerfCpuValidateGuid = {0xB760CFCC, 0xDEEF, 0x4C7E, {0x99, 0x5B, 0xED, 0xFE, 0xF2, 0x23, 0xB2, 0x09}}
+gPerfMeValidateGuid = {0x8CF7A498, 0x588D, 0x4D39, {0xBD, 0xAC, 0x51, 0x0C, 0x31, 0xAF, 0x45, 0xD0}}
+gPerfSaValidateGuid = {0xA73B382B, 0x62D4, 0x4A19, {0xBB, 0xF9, 0x09, 0x3E, 0xC5, 0xA5, 0x93, 0x11}}
+gPerfHeciPreMemGuid = {0xD815D922, 0x4994, 0x40B3, {0x97, 0xCC, 0x07, 0xF3, 0x7D, 0x42, 0xE7, 0x97}}
+gPerfPchPreMemGuid = {0xBB73E2B1, 0xB9FD, 0x4A80, {0xB8, 0x1A, 0x52, 0x39, 0xE9, 0x4D, 0x06, 0x2E}}
+gPerfCpuPreMemGuid = {0xAC5FCBC6, 0x084D, 0x445D, {0xB3, 0xF3, 0xCA, 0x16, 0xDE, 0xE9, 0xBB, 0x47}}
+gPerfMePreMemGuid = {0x6051338E, 0x0FFA, 0x40F7, {0xAF, 0xEF, 0xAB, 0x86, 0x7A, 0x38, 0xCC, 0xF3}}
+gPerfAmtPreMemGuid = {0xDB732D50, 0x9BB8, 0x489A, {0xA1, 0xD1, 0xDD, 0xD2, 0x16, 0x1D, 0x72, 0xB8}}
+gPerfAmtPostMemGuid = {0x0329D610, 0x4269, 0xD28F, {0x61, 0xBF, 0xB9, 0xA2, 0xD9, 0xFA, 0x96, 0x93}}
+gPerfSaPreMemGuid = {0x76F18BDA, 0x2195, 0x4FB6, {0x9A, 0x94, 0x0E, 0x0B, 0xAC, 0xDE, 0xEC, 0xAB}}
+gPerfEvlGuid = {0x8221518B, 0xAC19, 0x4E32, {0xAB, 0x5F, 0x00, 0x47, 0x0A, 0x50, 0x69, 0x40}}
+gPerfMemGuid = {0x2B57B316, 0x5CF7, 0x4847, {0xB0, 0x76, 0x6B, 0x5D, 0x23, 0xC3, 0xAA, 0x3E}}
+
+##
+## PostMem Performance
+##
+gPerfPchPostMemGuid = {0x70B67A99, 0x5556, 0x4315, {0xB3, 0x05, 0xD5, 0xDC, 0x4A, 0x35, 0x63, 0x70}}
+gPerfSaPostMemGuid = {0x9FF0CE92, 0x883F, 0x43DC, {0x8A, 0x07, 0xE0, 0xCB, 0x6D, 0x56, 0x7D, 0xE0}}
+gPerfS3CpuInitPostMemGuid = {0x976262C2, 0xD202, 0x4D12, {0x82, 0xAD, 0xF4, 0xA9, 0x8F, 0x9B, 0x96, 0x01}}
+gPerfSaSecLockPostMemGuid = {0x272AC110, 0x0B60, 0x4D07, {0xA5, 0x58, 0x6D, 0x73, 0xE2, 0x43, 0x85, 0x95}}
+gPerfCpuStrapPostMemGuid = {0x8EF4372B, 0x68F0, 0x4957, {0xBC, 0x4D, 0x7E, 0x5C, 0xFE, 0xDA, 0xB6, 0x3E}}
+gPerfMpPostMemGuid = {0xA59BAC5B, 0xC6A4, 0x4AEB, {0x84, 0x32, 0x7A, 0x8B, 0x6B, 0x68, 0x5F, 0x37}}
+gPerfCpuPostMemGuid = {0xE2FE5ED3, 0x1417, 0x451A, {0x95, 0xC9, 0xD0, 0xB2, 0xB9, 0x7B, 0xE0, 0x54}}
+gPerfSaResetPostMemGuid = {0xBE152BEE, 0xFD19, 0x4274, {0xA8, 0xBA, 0xFB, 0x31, 0x42, 0xB5, 0xB5, 0xC3}}
+gPerfCpuPowerMgmtGuid = {0x9ED307D6, 0x4AEB, 0x44A9, {0x9B, 0x11, 0xD8, 0x21, 0x84, 0x9A, 0xCB, 0xF7}}
+gPerfMePostMemGuid = {0x2CC8626D, 0x3387, 0x4817, {0xAB, 0xF6, 0x86, 0x9A, 0xF5, 0xF0, 0x51, 0xAA}}
+
+[Protocols]
+##
+## IntelFrameworkPkg
+##
+gEfiLegacyBiosProtocolGuid = {0xdb9a1e3d, 0x45cb, 0x4abb, {0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d}}
+gEfiLegacyInterruptProtocolGuid = {0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe}}
+gEfiLegacy8259ProtocolGuid = {0x38321dba, 0x4fe0, 0x4e17, {0x8a, 0xec, 0x41, 0x30, 0x55, 0xea, 0xed, 0xc1}}
+gEfiDataHubProtocolGuid = {0xae80d021, 0x618e, 0x11d4, {0xbc, 0xd7, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81}}
+##
+## MdeModulePkg
+##
+gEfiSmmVariableProtocolGuid = {0xed32d533, 0x99e6, 0x4209, {0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7}}
+##
+##
+##
+gSmbiosProcessorInfoHobGuid = {0xe6d73d92, 0xff56, 0x4146, {0xaf, 0xac, 0x1c, 0x18, 0x81, 0x7d, 0x68, 0x71}}
+
+##
+## SystemAgent
+##
+gBdatAccessGuid = {0x9477482c, 0x8717, 0x4725, {0x98, 0x28, 0x7b, 0xd8, 0xc9, 0xa3, 0x75, 0x6a}}
+gIgdOpRegionProtocolGuid = {0x9e67aecf, 0x4fbb, 0x4c84, {0x99, 0xa5, 0x10, 0x73, 0x40, 0x7, 0x6d, 0xb4}}
+gMemInfoProtocolGuid = {0xd4d2f201, 0x50e8, 0x4d45, {0x8e, 0x5, 0xfd, 0x49, 0xa8, 0x2a, 0x15, 0x69}}
+gSaPolicyProtocolGuid = {0xc6aa1f27, 0x5597, 0x4802, {0x9f, 0x63, 0xd6, 0x28, 0x36, 0x59, 0x86, 0x35}}
+gSaGlobalNvsAreaProtocolGuid = {0x3dc21d75, 0xde0e, 0x4300, {0xa0, 0xaa, 0x19, 0xc4, 0x1c, 0x0c, 0xf3, 0xdf}}
+gGopPolicyProtocolGuid = {0xec2e931b, 0x3281, 0x48a5, {0x81, 0x07, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d}}
+gGopComponentName2ProtocolGuid = {0x651b7ebd, 0xce13, 0x41d0, {0x82, 0xe5, 0xa0, 0x63, 0xab, 0xbe, 0x9b, 0xb6}}
+gGopOverrideProtocolGuid = {0x4a89a16e, 0x67b8, 0x4429, {0x8c, 0x47, 0x43, 0x67, 0x90, 0xf2, 0xf2, 0x69}}
+
+##
+## AcpiTables
+##
+gEfiGlobalNvsAreaProtocolGuid = {0x074e1e48, 0x8132, 0x47a1, {0x8c, 0x2c, 0x3f, 0x14, 0xad, 0x9a, 0x66, 0xdc}}
+##
+## Cpu
+##
+gCpuInfoProtocolGuid = {0xe223cf65, 0xf6ce, 0x4122, {0xb3, 0xaf, 0x4b, 0xd1, 0x8a, 0xff, 0x40, 0xa1}}
+gSmmBiosGuardProtocolGuid = {0x17565311, 0x4b71, 0x4340, {0x88, 0xaa, 0xdc, 0x9f, 0x44, 0x22, 0xe5, 0x3a}}
+gCpuGlobalNvsAreaProtocolGuid = {0xab5a4df4, 0xf0d7, 0x49a8, {0xbf, 0x5c, 0xf2, 0x5d, 0xa0, 0x4c, 0x25, 0x33}}
+
+##
+## PCH
+##
+gPchSpiProtocolGuid = {0xc7d289, 0x1347, 0x4de0, {0xbf, 0x42, 0xe, 0x26, 0x9d, 0xe, 0xf3, 0x4a}}
+gPchSerialGpioProtocolGuid = {0xf52c3858, 0x5ef8, 0x4d41, {0x83, 0x4e, 0xc3, 0x9e, 0xef, 0x8a, 0x45, 0xa3}}
+gWdtProtocolGuid = {0xb42b8d12, 0x2acb, 0x499a, {0xa9, 0x20, 0xdd, 0x5b, 0xe6, 0xcf, 0x09, 0xb1}}
+gPchInfoProtocolGuid = {0x984eb4e9, 0x5a95, 0x41de, {0xaa, 0xd0, 0x53, 0x66, 0x8c, 0xa5, 0x13, 0xc0}}
+gPchSerialIoUartDebugInfoProtocolGuid = {0x2fd2b1bd, 0x0387, 0x4ec6, {0x94, 0x1f, 0xf1, 0x4b, 0x7f, 0x1c, 0x94, 0xb6}}
+gEfiSmmSmbusProtocolGuid = {0x72e40094, 0x2ee1, 0x497a, {0x8f, 0x33, 0x4c, 0x93, 0x4a, 0x9e, 0x9c, 0x0c}}
+gPchSmmSpiProtocolGuid = {0x56521f06, 0xa62, 0x4822, {0x99, 0x63, 0xdf, 0x1, 0x9d, 0x72, 0xc7, 0xe1}}
+gPchSmmIoTrapControlGuid = {0x514d2afd, 0x2096, 0x4283, {0x9d, 0xa6, 0x70, 0x0c, 0xd2, 0x7d, 0xc7, 0xa5}}
+gPchTcoSmiDispatchProtocolGuid = {0x9e71d609, 0x6d24, 0x47fd, {0xb5, 0x72, 0x61, 0x40, 0xf8, 0xd9, 0xc2, 0xa4}}
+gPchPcieSmiDispatchProtocolGuid = {0x3e7d2b56, 0x3f47, 0x42aa, {0x8f, 0x6b, 0x22, 0xf5, 0x19, 0x81, 0x8d, 0xab}}
+gPchAcpiSmiDispatchProtocolGuid = {0xd52bb262, 0xf022, 0x49ec, {0x86, 0xd2, 0x7a, 0x29, 0x3a, 0x7a, 0x05, 0x4b}}
+gPchGpioUnlockSmiDispatchProtocolGuid = {0x83339ef7, 0x9392, 0x4716, {0x8d, 0x3a, 0xd1, 0xfc, 0x67, 0xcd, 0x55, 0xdb}}
+gPchSmiDispatchProtocolGuid = {0xE6A81BBF, 0x873D, 0x47FD, {0xB6, 0xBE, 0x61, 0xB3, 0xE5, 0x72, 0x09, 0x93}}
+gPchResetCallbackProtocolGuid = {0x3a3300ab, 0xc929, 0x487d, {0xab, 0x34, 0x15, 0x9b, 0xc1, 0x35, 0x62, 0xc0}}
+gPchResetProtocolGuid = {0xdb63592c, 0xb8cc, 0x44c8, {0x91, 0x8c, 0x51, 0xf5, 0x34, 0x59, 0x8a, 0x5a}}
+gPchNvsAreaProtocolGuid = {0x2e058b2b, 0xedc1, 0x4431, {0x87, 0xd9, 0xc6, 0xc4, 0xea, 0x10, 0x2b, 0xe3}}
+gPchEmmcTuningProtocolGuid = {0x10fe7e3b, 0xdbe5, 0x4cfa, {0x90, 0x25, 0x40, 0x02, 0xcf, 0xdd, 0xbb, 0x89}}
+gPchEspiSmiDispatchProtocolGuid = {0xB3C14FF3, 0xBAE8, 0x456C, {0x86, 0x31, 0x27, 0xFE, 0x0C, 0xEB, 0x34, 0x0C}}
+gPchSmmPeriodicTimerControlGuid = {0x6906E93B, 0x603B, 0x4A0F, {0x86, 0x92, 0x83, 0x20, 0x04, 0xAA, 0xF2, 0xDB}}
+
+##
+## Hsti
+##
+gHstiProtocolGuid = { 0x1b05de41, 0xc93b, 0x4bb4, { 0xad, 0x47, 0x2a, 0x78, 0xac, 0xf, 0xc9, 0xe4 }}
+gHstiPublishCompleteProtocolGuid = {0x0f500be6, 0xece4, 0x4ed8, { 0x90, 0x81, 0x9a, 0xa9, 0xa5, 0x23, 0xfb, 0x7b}}
+gEfiAdapterInformationProtocolGuid = { 0xE5DD1403, 0xD622, 0xC24E, {0x84, 0x88, 0xC7, 0x1B, 0x17, 0xF5, 0xE8, 0x02 }}
+
+##
+## Silicon Policy
+##
+gDxeSiPolicyProtocolGuid = { 0xeca27516, 0x306c, 0x4e28, { 0x8c, 0x94, 0x4e, 0x52, 0x10, 0x96, 0x69, 0x5e }}
+
+[Ppis]
+##
+## MdeModulePkg
+##
+gPeiCapsulePpiGuid = {0x3acf33ee, 0xd892, 0x40f4, {0xa2, 0xfc, 0x38, 0x54, 0xd2, 0xe1, 0x32, 0x3d}}
+gPeiSmmAccessPpiGuid = {0x268f33a9, 0xcccd, 0x48be, {0x88, 0x17, 0x86, 0x05, 0x3a, 0xc3, 0x2e, 0xd6}}
+gPeiSmmControlPpiGuid = {0x61c68702, 0x4d7e, 0x4f43, {0x8d, 0xef, 0xa7, 0x43, 0x05, 0xce, 0x74, 0xc5}}
+##
+## SecurityPkg
+##
+gPeiTpmInitializedPpiGuid = {0xe9db0d58, 0xd48d, 0x47f6, {0x9c, 0x6e, 0x6f, 0x40, 0xe8, 0x6c, 0x7b, 0x41}}
+gPeiTpmInitializationDonePpiGuid = {0xa030d115, 0x54dd, 0x447b, { 0x90, 0x64, 0xf2, 0x6, 0x88, 0x3d, 0x7c, 0xcc}}
+##
+## Common
+##
+gSiPolicyPpiGuid = {0xaebffa01, 0x7edc, 0x49ff, {0x8d, 0x88, 0xcb, 0x84, 0x8c, 0x5e, 0x86, 0x70}}
+gSiPreMemPolicyPpiGuid = {0xc133fe57, 0x17c7, 0x4b09, {0x8b, 0x3c, 0x97, 0xc1, 0x89, 0xd0, 0xab, 0x8d}}
+##
+## SystemAgent
+##
+gSsaBiosCallBacksPpiGuid = {0x99b56126, 0xe16c, 0x4d9b, {0xbb, 0x71, 0xaa, 0x35, 0x46, 0x1a, 0x70, 0x2f}}
+gSsaBiosServicesPpiGuid = {0x55750d10, 0x6d3d, 0x4bf5, {0x89, 0xd8, 0xe3, 0x5e, 0xf0, 0xb0, 0x90, 0xf4}}
+
+##
+## Cpu
+##
+##
+## PCH
+##
+gWdtPpiGuid = {0xf38d1338, 0xaf7a, 0x4fb6, {0x91, 0xdb, 0x1a, 0x9c, 0x21, 0x83, 0x57, 0x0d}}
+gPchSpiPpiGuid = {0xdade7ce3, 0x6971, 0x4b75, {0x82, 0x5e, 0xe, 0xe0, 0xeb, 0x17, 0x72, 0x2d}}
+gPeiSmbusPolicyPpiGuid = {0x63b6e435, 0x32bc, 0x49c6, {0x81, 0xbd, 0xb7, 0xa1, 0xa0, 0xfe, 0x1a, 0x6c}}
+gPchResetCallbackPpiGuid = {0x17865dc0, 0x0b8b, 0x4da8, {0x8b, 0x42, 0x7c, 0x46, 0xb8, 0x5c, 0xca, 0x4d}}
+gPchResetPpiGuid = {0x433e0f9f, 0x05ae, 0x410a, {0xa0, 0xc3, 0xbf, 0x29, 0x8e, 0xcb, 0x25, 0xac}}
+
+[LibraryClasses]
+## @libraryclass
+## Common
+##
+AslUpdateLib|Include/Library/AslUpdateLib.h
+MmPciLib|Include/Library/MmPciLib.h
+SiFviLib|Include/Library/SiFviLib.h
+SiPolicyLib|Include/Library/SiPolicyLib.h
+## @libraryclass
+## SampleCode
+##
+## CPU
+##
+BootGuardLib|Cpu/Include/Library/BootGuardLib.h
+CpuMailboxLib|Cpu/Include/Library/CpuMailboxLib.h
+CpuPlatformLib|Cpu/Include/Library/CpuPlatformLib.h
+CpuPolicyLib|Cpu/Include/Library/CpuPolicyLib.h
+CpuPolicyLibPreMem|Cpu/Include/Library/CpuPolicyLibPreMem.h
+TxtLib|Cpu/Include/Library/TxtLib.h
+## @libraryclass
+## Me
+##
+PeiMePolicyLib|Me/Include/Library/PeiMePolicyLib.h
+## @libraryclass
+## Pch
+##
+GpioLib|Pch/Include/Library/GpioLib.h
+GpioLib|Pch/Include/Library/GpioNativeLib.h
+PchCycleDecodingLib|Pch/Include/Library/PchCycleDecodingLib.h
+PchEspiLib|Pch/Include/Library/PchEspiLib.h
+PchGbeLib|Pch/Include/Library/PchGbeLib.h
+PchHsioLib|Pch/Include/Library/PchHsioLib.h
+PchInfoLib|Pch/Include/Library/PchInfoLib.h
+PchP2sbLib|Pch/Include/Library/PchP2sbLib.h
+PchPcieRpLib|Pch/Include/Library/PchPcieRpLib.h
+PchPcrLib|Pch/Include/Library/PchPcrLib.h
+PchPmcLib|Pch/Include/Library/PchPmcLib.h
+PchPolicyLib|Pch/Include/Library/PchPolicyLib.h
+PchSbiAccessLib|Pch/Include/Library/PchSbiAccessLib.h
+PchSerialIoLib|Pch/Include/Library/PchSerialIoLib.h
+PchSerialIoUartLib|Pch/Include/Library/PchSerialIoUartLib.h
+SecPchLib|Pch/Include/Library/SecPchLib.h
+TraceHubInitLib|Pch/Include/Library/TraceHubInitLib.h
+PchSmmControlLib|Pch/IncludePrivate/Library/PchSmmControlLib.h
+PchPsfLib|Pch/Include/Library/PchPsfLib.h
+PchWdtCommonLib|Pch/Include/Library/PchWdtCommonLib.h
+OcWdtLib|Pch/Include/Library/OcWdtLib.h
+PchResetLib|Pch/Include/Library/PchResetLib.h
+
+## @libraryclass
+## Sa
+##
+DxeSaPolicyLib|SystemAgent/Include/Library/DxeSaPolicyLib.h
+PeiSaPolicyLib|SystemAgent/Include/Library/PeiSaPolicyLib.h
+SaPlatformLib|SystemAgent/Include/Library/SaPlatformLib.h
+
+## @libraryclass
+## Memory
+##
+
+[PcdsFixedAtBuild]
+## From MdeModulePkg.dec
+## Progress Code for S3 Suspend end.
+## PROGRESS_CODE_S3_SUSPEND_END = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000001)) = 0x03078001
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd|0x03078001|UINT32|0x30001033
+##
+## PcdNemCodeCacheBase is usally the same as PEI FV Base address,
+## FLASH_BASE+FLASH_REGION_FV_RECOVERY_OFFSET from PlatformPkg.fdf.
+##
+## Restriction:
+## 1) PcdNemCodeCacheBase - (PcdTemporaryRamBase + PcdTemporaryRamSize) >= 4K
+## 2) PcdTemporaryRamBase >= 4G - 64M
+##
+gSiPkgTokenSpaceGuid.PcdNemCodeCacheBase|0xFFF80000|UINT32|0x20000009
+##
+## NemCodeCacheSize is usally the same as PEI FV Size,
+## FLASH_REGION_FV_RECOVERY_SIZE from PlatformPkg.fdf.
+##
+## Restriction:
+## 1) PcdNemTotalCacheSize = NemCodeCacheSize + PcdTemporaryRamSize
+## <= Maximun CPU NEM total size (Code + Data)
+## = LLC size - 0.5M
+## 2) PcdTemporaryRamSize <= Maximum CPU NEM data size
+## = MLC size
+## NOTE: The size restriction may be changed in next generation processor.
+## Please refer to Processor BWG for detail.
+##
+gSiPkgTokenSpaceGuid.PcdFlashAreaBaseAddress|0xFF800000|UINT32|0x10000001
+gSiPkgTokenSpaceGuid.PcdFlashAreaSize|0x00800000|UINT32|0x10000002
+gSiPkgTokenSpaceGuid.PcdTemporaryRamBase|0xfef00000|UINT32|0x00010028
+gSiPkgTokenSpaceGuid.PcdTemporaryRamSize|0x2000|UINT32|0x00010029
+gSiPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase|0xFFE60000|UINT32|0x30000004
+gSiPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize|0x000A0000|UINT32|0x30000005
+gSiPkgTokenSpaceGuid.PcdFlashMicrocodeFvOffset|0x00660000|UINT32|0x30000006
+##
+## PcdEfiGcdAllocateType is using for EFI_GCD_ALLOCATE_TYPE selection
+## value of the struct
+## 0x00 EfiGcdAllocateAnySearchBottomUp
+## 0x01 EfiGcdAllocateMaxAddressSearchBottomUp
+## 0x03 EfiGcdAllocateAnySearchTopDown
+## 0x04 EfiGcdAllocateMaxAddressSearchTopDown
+##
+## below value should not using in this situation
+## 0x05 EfiGcdMaxAllocateType : design for max value of struct
+## 0x02 EfiGcdAllocateAddress : design for speccification address allocate
+##
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType|0x01|UINT8|0x40000000
+gSiPkgTokenSpaceGuid.PcdSmmbaseSwSmi|0x55|UINT8|0x0010005
+gSiPkgTokenSpaceGuid.PcdPeiMinMemorySize|0x05000000|UINT32|0x30000007
+gSiPkgTokenSpaceGuid.PcdFspCpuPeiApWakeupBufferAddr|0x9f000|UINT32|0x30000008
+
+#
+# See HstiFeatureBit.h for the definition
+#
+gSiPkgTokenSpaceGuid.PcdHstiIhvFeature1|0xFF|UINT8|0x30000011
+gSiPkgTokenSpaceGuid.PcdHstiIhvFeature2|0x07|UINT8|0x30000012
+gSiPkgTokenSpaceGuid.PcdHstiIhvFeature3|0x00|UINT8|0x30000013
+
+[PcdsPatchableInModule]
+## From MdeModulePkg.dec
+## Default OEM ID for ACPI table creation, its length must be 0x6 bytes to follow ACPI specification.
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemId|"INTEL "|VOID*|0x30001034
+## Default OEM Table ID for ACPI table creation, it is "EDK2 ".
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemTableId|0x20202020324B4445|UINT64|0x30001035
+## Default OEM Revision for ACPI table creation.
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemRevision|0x00000002|UINT32|0x30001036
+## Default Creator ID for ACPI table creation.
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorId|0x20202020|UINT32|0x30001037
+## Default Creator Revision for ACPI table creation.
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision|0x01000013|UINT32|0x30001038
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+## Maximun number of performance log entries during PEI phase.
+gSiPkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|40|UINT8|0x0001002f
+## This value is used to set the base address of MCH
+gSiPkgTokenSpaceGuid.PcdMchBaseAddress|0xFED10000|UINT64|0x00010030
+gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress|0x0000EFA0|UINT16|0x00010031
+gSiPkgTokenSpaceGuid.PcdTcoBaseAddress|0x0400|UINT16|0x00010034
+gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress|0x1800|UINT16|0x00010035
+
+## 32KB window
+gSiPkgTokenSpaceGuid.PcdMchMmioSize|0x8000|UINT32|0x50000000
+
+## Stack size in the temporary RAM.
+## 0 means half of TemporaryRamSize.
+gSiPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0|UINT32|0x00010036
+##
+## PcdFviSmbiosType determines the SMBIOS OEM type (0x80 to 0xFF) defined in SMBIOS,
+## values 0-0x7F will be treated as disable FVI reporting.
+## FVI structure uses it as SMBIOS OEM type to provide version information.
+##
+gSiPkgTokenSpaceGuid.PcdFviSmbiosType|0xDD|UINT8|0x00010037
+gSiPkgTokenSpaceGuid.PcdSaPciPrint|FALSE|BOOLEAN|0x00010039
+##
+## SMBIOS defaults
+##
+gSiPkgTokenSpaceGuid.PcdSmbiosDefaultSocketDesignation|"U3E1"|VOID*|0x0001003a
+gSiPkgTokenSpaceGuid.PcdSmbiosDefaultSerialNumber|"To Be Filled By O.E.M."|VOID*|0x0001003b
+gSiPkgTokenSpaceGuid.PcdSmbiosDefaultAssetTag|"To Be Filled By O.E.M."|VOID*|0x0001003c
+gSiPkgTokenSpaceGuid.PcdSmbiosDefaultPartNumber|"To Be Filled By O.E.M."|VOID*|0x0001003d
+
+##
+## Allocate 56 KB [0x2000..0xFFFF] of I/O space for Pci Devices
+## If PcdPciReservedMemLimit =0 Pci Reserved default MMIO Limit is 0xE0000000 else use PcdPciReservedMemLimit .
+##
+gSiPkgTokenSpaceGuid.PcdPciReservedIobase |0x2000 |UINT16|0x00010041
+gSiPkgTokenSpaceGuid.PcdPciReservedIoLimit |0xFFFF |UINT16|0x00010042
+gSiPkgTokenSpaceGuid.PcdPciReservedMemLimit |0x0000 |UINT32|0x00010043
+
+##
+## Default 4MB TSEG for Release build BIOS when IED disabled (Also a default)
+##
+gSiPkgTokenSpaceGuid.PcdTsegSize|0x00400000|UINT32|0x00010044
+##
+## gSiPkgTokenSpaceGuid.PcdFwStsSmbiosType determines the SMBIOS OEM type (0x80 to 0xFF) defined
+## in SMBIOS, values 0-0x7F will be treated as disable FWSTS SMBIOS reporting.
+## FWSTS structure uses it as SMBIOS OEM type to provide FWSTS information.
+##
+gSiPkgTokenSpaceGuid.PcdFwStsSmbiosType|0xDB|UINT8|0x00010045
+
+##
+## Maximum Address the AP Wakeup Buffer can start.
+##
+gSiPkgTokenSpaceGuid.PcdCpuApWakeupBufferMaxAddr|0x58000|UINT32|0x00010046
+
+##
+## Silicon Reference Code versions
+##
+gSiPkgTokenSpaceGuid.PcdSiliconInitVersionMajor |2|UINT8|0x00010047
+gSiPkgTokenSpaceGuid.PcdSiliconInitVersionMinor |3|UINT8|0x00010048
+gSiPkgTokenSpaceGuid.PcdSiliconInitVersionRevision|0|UINT8|0x00010049
+gSiPkgTokenSpaceGuid.PcdSiliconInitVersionBuild |0|UINT8|0x00010050
+
+## Null-terminated string of the Version of Physical Presence interface supported by platform.
+# @Prompt Version of Physical Presence interface supported by platform.
+gSiPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|"1.3"|VOID*|0x00000008
+
+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
+##
+## SerialIo Uart Configuration
+##
+gSiPkgTokenSpaceGuid.PcdSerialIoUartDebugEnable |0 |UINT8 |0x00100001 # 0:Disable, 1:Enable and Initialize, 2:Enable without Initializing
+gSiPkgTokenSpaceGuid.PcdSerialIoUartNumber |2 |UINT8 |0x00100002
+gSiPkgTokenSpaceGuid.PcdSerialIoUartInputClock |1843200|UINT32|0x00100003
+##
+## PCI Express MMIO region length
+## Valid settings: 0x10000000/256MB, 0x8000000/128MB, 0x4000000/64MB
+##
+gSiPkgTokenSpaceGuid.PcdPciExpressRegionLength|0x10000000|UINT32|0x0010004
+
+
+[PcdsFeatureFlag]
+##
+## Those PCDs are used to control build process.
+##
+gSiPkgTokenSpaceGuid.PcdTraceHubEnable |FALSE|BOOLEAN|0xF0000001
+gSiPkgTokenSpaceGuid.PcdSmmVariableEnable |FALSE|BOOLEAN|0xF0000002
+gSiPkgTokenSpaceGuid.PcdSerialGpioEnable |FALSE|BOOLEAN|0xF0000003
+gSiPkgTokenSpaceGuid.PcdAtaEnable |FALSE|BOOLEAN|0xF0000004
+gSiPkgTokenSpaceGuid.PcdSiCsmEnable |FALSE|BOOLEAN|0xF0000005
+gSiPkgTokenSpaceGuid.PcdUseHpetTimer |FALSE|BOOLEAN|0xF0000006
+gSiPkgTokenSpaceGuid.PcdSgEnable |TRUE |BOOLEAN|0xF0000008
+gSiPkgTokenSpaceGuid.PcdAcpiEnable |TRUE |BOOLEAN|0xF0000009
+gSiPkgTokenSpaceGuid.PcdSourceDebugEnable |FALSE|BOOLEAN|0xF000000B
+gSiPkgTokenSpaceGuid.PcdPpmEnable |TRUE |BOOLEAN|0xF000000C
+gSiPkgTokenSpaceGuid.PcdTxtEnable |TRUE |BOOLEAN|0xF000000D
+gSiPkgTokenSpaceGuid.PcdIntegratedTouchEnable |FALSE|BOOLEAN|0xF000000F
+gSiPkgTokenSpaceGuid.PcdAmtEnable |FALSE|BOOLEAN|0xF0000010
+gSiPkgTokenSpaceGuid.PcdPttEnable |FALSE|BOOLEAN|0xF0000011
+gSiPkgTokenSpaceGuid.PcdJhiEnable |FALSE|BOOLEAN|0xF0000012
+gSiPkgTokenSpaceGuid.PcdSoftwareGuardEnable |FALSE|BOOLEAN|0xF0000013
+gSiPkgTokenSpaceGuid.PcdSmbiosEnable |TRUE |BOOLEAN|0xF0000014
+gSiPkgTokenSpaceGuid.PcdS3Enable |TRUE |BOOLEAN|0xF0000015
+gSiPkgTokenSpaceGuid.PcdOverclockEnable |FALSE|BOOLEAN|0xF0000016
+gSiPkgTokenSpaceGuid.PcdCpuPowerOnConfigEnable |FALSE|BOOLEAN|0xF0000017
+gSiPkgTokenSpaceGuid.PcdSsaFlagEnable |FALSE|BOOLEAN|0xF0000018
+gSiPkgTokenSpaceGuid.PcdEvLoaderEnable |FALSE|BOOLEAN|0xF0000019
+gSiPkgTokenSpaceGuid.PcdIgdEnable |TRUE |BOOLEAN|0xF000001A
+gSiPkgTokenSpaceGuid.PcdPegEnable |TRUE |BOOLEAN|0xF000001B
+gSiPkgTokenSpaceGuid.PcdSaDmiEnable |TRUE |BOOLEAN|0xF000001C
+gSiPkgTokenSpaceGuid.PcdSkycamEnable |TRUE |BOOLEAN|0xF000001D
+gSiPkgTokenSpaceGuid.PcdGmmEnable |TRUE |BOOLEAN|0xF000001E
+gSiPkgTokenSpaceGuid.PcdSaOcEnable |TRUE |BOOLEAN|0xF000001F
+gSiPkgTokenSpaceGuid.PcdVtdEnable |TRUE |BOOLEAN|0xF0000020
+gSiPkgTokenSpaceGuid.PcdBiosGuardEnable |FALSE|BOOLEAN|0xF0000021
+gSiPkgTokenSpaceGuid.PcdBdatEnable |FALSE|BOOLEAN|0xF0000023
+gSiPkgTokenSpaceGuid.PcdOptimizeCompilerEnable |FALSE|BOOLEAN|0xF0000024
+gSiPkgTokenSpaceGuid.PcdPeiDisplayEnable |TRUE |BOOLEAN|0xF0000025
+gSiPkgTokenSpaceGuid.PcdPowerOnEnable |FALSE|BOOLEAN|0xF0000027
+gSiPkgTokenSpaceGuid.PcdOcWdtEnable |FALSE|BOOLEAN|0xF0000028
+gSiPkgTokenSpaceGuid.PcdBootGuardEnable |FALSE|BOOLEAN|0xF0000029
+gSiPkgTokenSpaceGuid.PcdMinTreeEnable |FALSE|BOOLEAN|0xF000002A # To separate modules used in mininal source tree and advanced features
+gSiPkgTokenSpaceGuid.PcdSiCatalogDebugEnable |FALSE|BOOLEAN|0xF000002B
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SiPkgBuildOption.dsc b/Silicon/Intel/KabylakeSiliconPkg/SiPkgBuildOption.dsc
new file mode 100644
index 0000000000..f313e4c352
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SiPkgBuildOption.dsc
@@ -0,0 +1,119 @@
+## @file
+# Silicon build option configuration file.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[BuildOptions]
+# Define Build Options both for EDK and EDKII drivers.
+
+
+
+# SA
+ DEFINE PTT_BUILD_OPTION =
+
+
+ DEFINE SIMICS_BUILD_OPTIONS =
+
+!if gSiPkgTokenSpaceGuid.PcdSgEnable == TRUE
+ DEFINE DSC_SG_BUILD_OPTIONS = -DSG_SUPPORT=1
+!else
+ DEFINE DSC_SG_BUILD_OPTIONS =
+!endif
+
+!if gSiPkgTokenSpaceGuid.PcdBdatEnable == TRUE
+ DEFINE BDAT_BUILD_OPTION = -DBDAT_SUPPORT=1
+!else
+ DEFINE BDAT_BUILD_OPTION =
+!endif
+
+!if gSiPkgTokenSpaceGuid.PcdSsaFlagEnable == TRUE
+ DEFINE DSC_SSA_BUILD_OPTIONS = -DSSA_FLAG=1 -DSSA_CLIENT_FLAG=1
+ DEFINE BDAT_BUILD_OPTION = -DBDAT_SUPPORT=1
+!else
+ DEFINE DSC_SSA_BUILD_OPTIONS =
+!endif
+
+ DEFINE DSC_AMT_BUILD_OPTIONS =
+
+ DEFINE SLE_BUILD_OPTIONS =
+!if $(TARGET) == RELEASE
+!if gSiPkgTokenSpaceGuid.PcdSiCatalogDebugEnable == TRUE
+ DEFINE DEBUG_BUILD_OPTIONS =
+!else
+ # MDEPKG_NDEBUG is introduced for the intention
+ # of size reduction when compiler optimization is disabled. If MDEPKG_NDEBUG is
+ # defined, then debug and assert related macros wrapped by it are the NULL implementations.
+ DEFINE DEBUG_BUILD_OPTIONS = -DMDEPKG_NDEBUG
+!endif
+!else
+ DEFINE DEBUG_BUILD_OPTIONS =
+!endif
+
+!if gSiPkgTokenSpaceGuid.PcdOptimizeCompilerEnable == FALSE
+ DEFINE OPTIMIZE_DISABLE_OPTIONS = -Od -GL-
+!else
+ DEFINE OPTIMIZE_DISABLE_OPTIONS =
+!endif
+
+DEFINE DSC_SIPKG_FEATURE_BUILD_OPTIONS = $(BDAT_BUILD_OPTION) $(PTT_BUILD_OPTION) $(DEBUG_BUILD_OPTIONS) $(DSC_SSA_BUILD_OPTIONS) $(DSC_AMT_BUILD_OPTIONS)
+DEFINE DSC_SIPKG_FEATURE_BUILD_OPTIONS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(DSC_SG_BUILD_OPTIONS) $(SIMICS_BUILD_OPTIONS)
+
+
+[BuildOptions.Common.EDKII]
+
+#
+# For IA32 Global Build Flag
+#
+ *_*_IA32_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015 -DASF_PEI
+ *_*_IA32_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_IA32_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_IA32_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_IA32_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+
+#
+# For IA32 Specific Build Flag
+#
+GCC: *_*_IA32_PP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_IA32_ASM_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_IA32_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015 -DASF_PEI
+MSFT: *_*_IA32_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_IA32_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_IA32_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_IA32_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+
+#
+# For X64 Global Build Flag
+#
+ *_*_X64_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015
+ *_*_X64_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_X64_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_X64_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_X64_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+
+#
+# For X64 Specific Build Flag
+#
+GCC: *_*_X64_PP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_X64_ASM_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_X64_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015
+MSFT: *_*_X64_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_X64_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_X64_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_X64_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+
+
+[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
+GCC: *_*_*_DLINK_FLAGS = -z common-page-size=0x1000
+MSFT: *_*_*_DLINK_FLAGS = /ALIGN:4096
+XCODE: *_*_*_DLINK_FLAGS = -segalign 0x1000
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SiPkgCommonLib.dsc b/Silicon/Intel/KabylakeSiliconPkg/SiPkgCommonLib.dsc
new file mode 100644
index 0000000000..eb7d43191f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SiPkgCommonLib.dsc
@@ -0,0 +1,73 @@
+## @file
+# Component description file for the SkyLake SiPkg both Pei and Dxe libraries DSC file.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+#
+# Silicon Init Common Library
+#
+
+#
+# Common
+#
+ MmPciLib|$(PLATFORM_SI_PACKAGE)/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
+
+#
+# Cpu
+#
+
+CpuPlatformLib|$(PLATFORM_SI_PACKAGE)/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf
+
+
+ CpuMailboxLib|$(PLATFORM_SI_PACKAGE)/Cpu/Library/BaseCpuMailboxLibNull/BaseCpuMailboxLibNull.inf
+#
+# Me
+#
+
+#
+# Pch
+#
+ PchCycleDecodingLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
+ PchGbeLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf
+ PchHsioLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf
+ PchInfoLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
+ PchP2sbLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf
+ PchPcieRpLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf
+ PchPcrLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
+ PchPmcLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf
+ PchSbiAccessLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
+ GpioLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
+ PchSerialIoLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf
+ PchWdtCommonLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf
+ ResetSystemLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
+ SmbusLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf
+ #private
+ PchPciExpressHelpersLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
+ PchInitCommonLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
+ PchSmbusCommonLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf
+ PchSpiCommonLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
+ GpioPrivateLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf
+ I2cMasterCommonLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf
+ PchPsfPrivateLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf
+ PchPsfLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf
+ RstPrivateLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf
+
+
+#
+# SA
+#
+ SaPlatformLib|$(PLATFORM_SI_PACKAGE)/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf
+
+#
+# Memory
+#
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SiPkgDxe.dsc b/Silicon/Intel/KabylakeSiliconPkg/SiPkgDxe.dsc
new file mode 100644
index 0000000000..4fe0f8d18c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SiPkgDxe.dsc
@@ -0,0 +1,73 @@
+## @file
+# Component description file for the SkyLake SiPkg DXE drivers.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+#
+# Common
+#
+
+#
+# Pch
+#
+ $(PLATFORM_SI_PACKAGE)/Pch/PchInit/Dxe/PchInitDxe.inf
+ $(PLATFORM_SI_PACKAGE)/Pch/SmmControl/RuntimeDxe/SmmControl.inf
+
+ $(PLATFORM_SI_PACKAGE)/Pch/Spi/Smm/PchSpiSmm.inf
+
+
+
+ $(PLATFORM_SI_PACKAGE)/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
+ $(PLATFORM_SI_PACKAGE)/Pch/PchInit/Smm/PchInitSmm.inf
+
+#
+# SystemAgent
+#
+ $(PLATFORM_SI_PACKAGE)/SystemAgent/SmmAccess/Dxe/SmmAccess.inf
+ $(PLATFORM_SI_PACKAGE)/SystemAgent/SaInit/Dxe/SaInitDxe.inf {
+ <LibraryClasses>
+!if $(TARGET) == DEBUG
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!endif
+ }
+
+
+!if gSiPkgTokenSpaceGuid.PcdAcpiEnable == TRUE
+ $(PLATFORM_SI_PACKAGE)/SystemAgent/AcpiTables/SaAcpiTables.inf
+ $(PLATFORM_SI_PACKAGE)/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf
+!endif
+
+#
+# Cpu
+#
+
+
+
+
+#
+# Me
+#
+
+
+
+
+
+
+ $(PLATFORM_SI_PACKAGE)/Hsti/Dxe/HstiSiliconDxe.inf {
+ <LibraryClasses>
+ HstiLib|MdePkg/Library/DxeHstiLib/DxeHstiLib.inf
+!if $(TARGET) == DEBUG
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!endif
+ }
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SiPkgDxeLib.dsc b/Silicon/Intel/KabylakeSiliconPkg/SiPkgDxeLib.dsc
new file mode 100644
index 0000000000..9697da6c30
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SiPkgDxeLib.dsc
@@ -0,0 +1,47 @@
+# @file
+# Component description file for the SkyLake SiPkg DXE libraries.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+#
+# Silicon Init Dxe Library
+#
+
+#
+# Common
+#
+!if gSiPkgTokenSpaceGuid.PcdAcpiEnable == TRUE
+ AslUpdateLib|$(PLATFORM_SI_PACKAGE)/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf
+!else
+ AslUpdateLib|$(PLATFORM_SI_PACKAGE)/Library/DxeAslUpdateLibNull/DxeAslUpdateLibNull.inf
+!endif
+
+#
+# Cpu
+#
+ CpuCommonLib|$(PLATFORM_SI_PACKAGE)/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/PeiDxeSmmCpuCommonLib.inf
+
+#
+# Pch
+#
+ PchHdaLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf
+ ResetSystemLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf
+
+#
+# Me
+#
+
+#
+# SystemAgent
+#
+ DxeSaPolicyLib|$(PLATFORM_SI_PACKAGE)/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SiPkgPei.dsc b/Silicon/Intel/KabylakeSiliconPkg/SiPkgPei.dsc
new file mode 100644
index 0000000000..a2bc1cd49f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SiPkgPei.dsc
@@ -0,0 +1,28 @@
+## @file
+# Component description file for the SkyLake SiPkg PEI drivers.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+#
+# Common
+#
+
+#
+# SystemAgent
+#
+
+#
+# Cpu
+#
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SiPkgPeiLib.dsc b/Silicon/Intel/KabylakeSiliconPkg/SiPkgPeiLib.dsc
new file mode 100644
index 0000000000..b81a736486
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SiPkgPeiLib.dsc
@@ -0,0 +1,54 @@
+## @file
+# Component description file for the SkyLake SiPkg PEI libraries.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+#
+# Silicon Init Pei Library
+#
+ SiPolicyLib|$(PLATFORM_SI_PACKAGE)/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf
+ SiConfigBlockLib|$(PLATFORM_SI_PACKAGE)/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
+
+#
+# Pch
+#
+ PchPolicyLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf
+!if gSiPkgTokenSpaceGuid.PcdOcWdtEnable == TRUE
+ OcWdtLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf
+!else
+ OcWdtLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf
+!endif
+ ResetSystemLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf
+ PchResetLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf
+
+#
+# Cpu
+#
+ CpuCommonLib|$(PLATFORM_SI_PACKAGE)/Cpu/LibraryPrivate/PeiDxeSmmCpuCommonLib/PeiDxeSmmCpuCommonLib.inf
+
+#
+# Me
+#
+ PeiMePolicyLib|$(PLATFORM_SI_PACKAGE)/Me/Library/PeiMePolicyLib/PeiMePolicyLib.inf
+
+#
+# SA
+#
+
+ PeiSaPolicyLib|$(PLATFORM_SI_PACKAGE)/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.inf
+#
+# Cpu
+#
+ CpuPolicyLib|$(PLATFORM_SI_PACKAGE)/Cpu/Library/PeiCpuPolicyLib/PeiCpuPolicyLib.inf
+ CpuPolicyLibPreMem|$(PLATFORM_SI_PACKAGE)/Cpu/Library/PeiCpuPolicyLibPreMem/PeiCpuPolicyLibPreMem.inf
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.aslc b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.aslc
new file mode 100644
index 0000000000..bf7b56e23e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.aslc
@@ -0,0 +1,411 @@
+/** @file
+ This file describes the contents of the ACPI DMA address Remapping
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "Dmar.h"
+
+EFI_ACPI_DMAR_TABLE DmarTable = {
+ {
+ EFI_ACPI_VTD_DMAR_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_DMAR_TABLE),
+ EFI_ACPI_DMAR_TABLE_REVISION,
+
+ //
+ // Checksum will be updated at runtime
+ //
+ 0x00,
+
+ //
+ // It is expected that these values will be programmed at runtime
+ //
+ { 'I', 'N', 'T', 'E', 'L', ' ' },
+ EFI_ACPI_DMAR_OEM_TABLE_ID,
+ 0x1,
+ EFI_ACPI_DMAR_OEM_CREATOR_ID,
+ 1
+ },
+
+ //
+ // DMAR table specific entries below:
+ //
+
+ //
+ // 39-bit addressing Host Address Width
+ //
+ 38,
+
+ //
+ // Flags
+ //
+ 0,
+
+ //
+ // Reserved fields
+ //
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+
+ //
+ // First DRHD structure, VT-d Engine #1
+ //
+ {
+ 0, // Type = 0 (DRHD)
+ sizeof (EFI_ACPI_DRHD_ENGINE1_STRUCT), // Length of structure
+ 0, // Flag - Do not include all
+ 0, // Reserved fields
+ 0, // Segment
+ 0x00000000, // Base address of DMA-remapping hardware - Updated at boot time
+
+ //
+ // Device Scopes
+ //
+ {
+ {
+ 1, // Type
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Segment number
+ 0, // Reserved
+ 0, // Start bus number
+ {2, 0} // PCI path
+ }
+ }
+ },
+
+ //Second DRHD structure VT-d Engine# 2
+ {
+ 0, // Type = 0 (DRHD)
+ sizeof(EFI_ACPI_DRHD_ENGINE2_STRUCT), // Length of strucure.
+ 1, // Flag - Include all
+ 0, // Reserved
+ 0, // Segment Number
+ 0x00000000, // Base address of DMA-remapping hardware.
+
+ {
+ //
+ // Device Scopes
+ //
+ {
+ 3, // Type=IO APIC
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 2, // Enumeration ID
+ 0xF0, // Start bus number
+ {31, 0} // PCI path
+ },
+ //
+ // Device Scopes
+ //
+ {
+ 4, // Type=HPET
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 0, // Enumeration ID
+ 0xF0, // Start bus number
+ {31, 0} // PCI path
+ },
+ //
+ // Device Scopes - I2C0
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 1, // Enumeration ID
+ 0, // Start bus number
+ {21, 0} // PCI path
+ },
+ //
+ // Device Scopes - I2C1
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 2, // Enumeration ID
+ 0, // Start bus number
+ {21, 1} // PCI path
+ },
+ //
+ // Device Scopes - I2C2
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 3, // Enumeration ID
+ 0, // Start bus number
+ {21, 2} // PCI path
+ },
+ //
+ // Device Scopes - I2C3
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 4, // Enumeration ID
+ 0, // Start bus number
+ {21, 3} // PCI path
+ },
+ //
+ // Device Scopes - I2C4 (LP only)
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 5, // Enumeration ID
+ 0, // Start bus number
+ {25, 2} // PCI path
+ },
+ //
+ // Device Scopes - I2C5 (LP only)
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 6, // Enumeration ID
+ 0, // Start bus number
+ {25, 1} // PCI path
+ },
+ //
+ // Device Scopes - SPI0
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 7, // Enumeration ID
+ 0, // Start bus number
+ {30, 2} // PCI path
+ },
+ //
+ // Device Scopes - SPI1
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 8, // Enumeration ID
+ 0, // Start bus number
+ {30, 3} // PCI path
+ },
+ //
+ // Device Scopes - UA00
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 9, // Enumeration ID
+ 0, // Start bus number
+ {30, 0} // PCI path
+ },
+ //
+ // Device Scopes - UA01
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 10, // Enumeration ID
+ 0, // Start bus number
+ {30, 1} // PCI path
+ },
+ //
+ // Device Scopes - UA02
+ //
+ {
+ 5, // Type=ACPI_NAMESPACE_DEVICE
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 11, // Enumeration ID
+ 0, // Start bus number
+ {25, 0} // PCI path
+ }
+ }
+ },
+
+ //RMRR structure for USB devices.
+ {
+ 0x1, // Type 1 - RMRR structure
+ sizeof(EFI_ACPI_RMRR_USB_STRUC), // Length
+ 0x0000, // Reserved
+ 0x0000, // Segment Num
+ 0x00000000000E0000, // RMRR Base address - Updated in runtime.
+ 0x00000000000EFFFF, // RMRR Limit address - Updated in runtime.
+ {
+ {
+ 1, // Type
+ sizeof(EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 0, // Enum ID
+ 0, // Start bus number
+ {20, 0} // PCI path
+ },
+ {
+ 1, // Type
+ sizeof(EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 0, // Enum ID
+ 0, // Start bus number
+ {20, 1} // PCI path
+ }
+ }
+ },
+
+ //RMRR structure for IGD device.
+ {
+ 1, // Type 1 - RMRR structure
+ sizeof(EFI_ACPI_RMRR_IGD_STRUC), // Length
+ 0x0000, // Reserved
+ 0x0000, // Segment Num
+ 0x0000000000000000, // RMRR Base address - Updated in runtime.
+ 0x0000000000000000, // RMRR Limit address - Updated in runtime.
+ {
+ {
+ 1, // Type
+ sizeof(EFI_ACPI_DEV_SCOPE_STRUCTURE), // Length
+ 0, // Reserved
+ 0, // Enum ID
+ 0, // Start bus number
+ {2, 0} // PCI path
+ }
+ }
+ },
+
+ // SKL ANDD structure.
+ // device path string limit is 20 including '\0'
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 1,
+ "\\_SB.PCI0.I2C0"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 2,
+ "\\_SB.PCI0.I2C1"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 3,
+ "\\_SB.PCI0.I2C2"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 4,
+ "\\_SB.PCI0.I2C3"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 5,
+ "\\_SB.PCI0.I2C4"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 6,
+ "\\_SB.PCI0.I2C5"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 7,
+ "\\_SB.PCI0.SPI0"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 8,
+ "\\_SB.PCI0.SPI1"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 9,
+ "\\_SB.PCI0.UA00"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 10,
+ "\\_SB.PCI0.UA01"
+ },
+
+ // ANDD structure.
+ {
+ 4, // Type 4 - ANDD structure
+ sizeof(EFI_ACPI_ANDD_STRUC), // Length
+ { 0, 0, 0 }, // Reserved [3]
+ 11,
+ "\\_SB.PCI0.UA02"
+ }
+};
+
+//
+// Dummy function required for build tools
+//
+#if defined (__GNUC__)
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&DmarTable;
+}
+#else
+int
+main (
+ VOID
+ )
+{
+ return 0;
+}
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.h
new file mode 100644
index 0000000000..aaa027806b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/Dmar/Dmar.h
@@ -0,0 +1,30 @@
+/** @file
+ This file describes the contents of the ACPI DMA address Remapping
+ Some additional ACPI values are defined in Acpi1_0.h and Acpi2_0.h.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_DMAR_H_
+#define _SA_DMAR_H_
+
+///
+/// Include standard ACPI table definitions
+///
+#include <IndustryStandard/Acpi30.h>
+#include <DmaRemappingTable.h>
+
+#pragma pack(1)
+
+#define EFI_ACPI_DMAR_OEM_TABLE_ID 0x204C424B ///< "KBL "
+#define EFI_ACPI_DMAR_OEM_CREATOR_ID 0x4C544E49 ///< "INTL"
+#pragma pack()
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/HostBus.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/HostBus.asl
new file mode 100644
index 0000000000..ea14d5d479
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/HostBus.asl
@@ -0,0 +1,733 @@
+/** @file
+ This file contains the SystemAgent PCI Configuration space
+ definition.
+ It defines various System Agent PCI Configuration Space registers
+ which will be used to dynamically produce all resources in the Host Bus.
+ @note This ASL file needs to be included as part of platform ACPI DSDT table.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+External(M64B)
+External(M64L)
+External(M32B)
+External(M32L)
+
+//
+// Define various System Agent (SA) PCI Configuration Space
+// registers which will be used to dynamically produce all
+// resources in the Host Bus _CRS.
+//
+OperationRegion (HBUS, PCI_Config, 0x00, 0x100)
+Field (HBUS, DWordAcc, NoLock, Preserve)
+{
+ Offset(0x40), // EPBAR (0:0:0:40)
+ EPEN, 1, // Enable
+ , 11,
+ EPBR, 20, // EPBAR [31:12]
+
+ Offset(0x48), // MCHBAR (0:0:0:48)
+ MHEN, 1, // Enable
+ , 14,
+ MHBR, 17, // MCHBAR [31:15]
+
+ Offset(0x50), // GGC (0:0:0:50)
+ GCLK, 1, // GGCLCK
+
+ Offset(0x54), // DEVEN (0:0:0:54)
+ D0EN, 1, // DEV0 Enable
+
+ Offset(0x60), // PCIEXBAR (0:0:0:60)
+ PXEN, 1, // Enable
+ PXSZ, 2, // PCI Express Size
+ , 23,
+ PXBR, 6, // PCI Express BAR [31:26]
+
+ Offset(0x68), // DMIBAR (0:0:0:68)
+ DIEN, 1, // Enable
+ , 11,
+ DIBR, 20, // DMIBAR [31:12]
+
+ Offset(0x70), // MESEG_BASE (0:0:0:70)
+ , 20,
+ MEBR, 12, // MESEG_BASE [31:20]
+
+ Offset(0x80), // PAM0 Register (0:0:0:80)
+ PMLK, 1, // PAM Lock bit.
+ , 3,
+ PM0H, 2, // PAM 0, High Nibble
+ , 2,
+
+ Offset(0x81), // PAM1 Register (0:0:0:81)
+ PM1L, 2, // PAM1, Low Nibble
+ , 2,
+ PM1H, 2, // PAM1, High Nibble
+ , 2,
+
+ Offset(0x82), // PAM2 Register (0:0:0:82)
+ PM2L, 2, // PAM2, Low Nibble
+ , 2,
+ PM2H, 2, // PAM2, High Nibble
+ , 2,
+
+ Offset(0x83), // PAM3 Register (0:0:0:83)
+ PM3L, 2, // PAM3, Low Nibble
+ , 2,
+ PM3H, 2, // PAM3, High Nibble
+ , 2,
+
+ Offset(0x84), // PAM4 Register (0:0:0:84)
+ PM4L, 2, // PAM4, Low Nibble
+ , 2,
+ PM4H, 2, // PAM4, High Nibble
+ , 2,
+
+ Offset(0x85), // PAM5 Register (0:0:0:85)
+ PM5L, 2, // PAM5, Low Nibble
+ , 2,
+ PM5H, 2, // PAM5, High Nibble
+ , 2,
+
+ Offset(0x86), // PAM6 Register (0:0:0:86)
+ PM6L, 2, // PAM6, Low Nibble
+ , 2,
+ PM6H, 2, // PAM6, High Nibble
+ , 2,
+
+ Offset(0xA8), // Top of Upper Usable DRAM Register (0:0:0:A8)
+ , 20,
+ TUUD, 19, // TOUUD [38:20]
+
+ Offset(0xBC), // Top of Lower Usable DRAM Register (0:0:0:BC)
+ , 20,
+ TLUD, 12, // TOLUD [31:20]
+}
+//
+// Define a buffer that will store all the bus, memory, and IO information
+// relating to the Host Bus. This buffer will be dynamically altered in
+// the _CRS and passed back to the OS.
+//
+Name(BUF0,ResourceTemplate()
+{
+ //
+ // Bus Number Allocation: Bus 0 to 0xFF
+ //
+ WORDBusNumber(ResourceProducer,MinFixed,MaxFixed,PosDecode,0x00,
+ 0x0000,0x00FF,0x00,0x0100,,,PB00)
+
+ //
+ // I/O Region Allocation 0 ( 0x0000 - 0x0CF7 )
+ //
+ DWordIo(ResourceProducer,MinFixed,MaxFixed,PosDecode,EntireRange,
+ 0x00,0x0000,0x0CF7,0x00,0x0CF8,,,PI00)
+
+ //
+ // PCI Configuration Registers ( 0x0CF8 - 0x0CFF )
+ //
+ Io(Decode16,0x0CF8,0x0CF8,1,0x08)
+
+ //
+ // I/O Region Allocation 1 ( 0x0D00 - 0xFFFF )
+ //
+ DWordIo(ResourceProducer,MinFixed,MaxFixed,PosDecode,EntireRange,
+ 0x00,0x0D00,0xFFFF,0x00,0xF300,,,PI01)
+
+ //
+ // Video Buffer Area ( 0xA0000 - 0xBFFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xA0000,0xBFFFF,0x00,0x20000,,,A000)
+
+ //
+ // ISA Add-on BIOS Area ( 0xC0000 - 0xC3FFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xC0000,0xC3FFF,0x00,0x4000,,,C000)
+
+ //
+ // ISA Add-on BIOS Area ( 0xC4000 - 0xC7FFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xC4000,0xC7FFF,0x00,0x4000,,,C400)
+
+ //
+ // ISA Add-on BIOS Area ( 0xC8000 - 0xCBFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xC8000,0xCBFFF,0x00,0x4000,,,C800)
+
+ //
+ // ISA Add-on BIOS Area ( 0xCC000 - 0xCFFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xCC000,0xCFFFF,0x00,0x4000,,,CC00)
+
+ //
+ // ISA Add-on BIOS Area ( 0xD0000 - 0xD3FFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xD0000,0xD3FFF,0x00,0x4000,,,D000)
+
+ //
+ // ISA Add-on BIOS Area ( 0xD4000 - 0xD7FFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xD4000,0xD7FFF,0x00,0x4000,,,D400)
+
+ //
+ // ISA Add-on BIOS Area ( 0xD8000 - 0xDBFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xD8000,0xDBFFF,0x00,0x4000,,,D800)
+
+ //
+ // ISA Add-on BIOS Area ( 0xDC000 - 0xDFFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xDC000,0xDFFFF,0x00,0x4000,,,DC00)
+
+ //
+ // BIOS Extension Area ( 0xE0000 - 0xE3FFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xE0000,0xE3FFF,0x00,0x4000,,,E000)
+
+ //
+ // BIOS Extension Area ( 0xE4000 - 0xE7FFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xE4000,0xE7FFF,0x00,0x4000,,,E400)
+
+ //
+ // BIOS Extension Area ( 0xE8000 - 0xEBFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xE8000,0xEBFFF,0x00,0x4000,,,E800)
+
+ //
+ // BIOS Extension Area ( 0xEC000 - 0xEFFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xEC000,0xEFFFF,0x00,0x4000,,,EC00)
+
+ //
+ // BIOS Area ( 0xF0000 - 0xFFFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+ ReadWrite,0x00,0xF0000,0xFFFFF,0x00,0x10000,,,F000)
+
+// //
+// // Memory Hole Region ( 0xF00000 - 0xFFFFFF )
+// //
+// DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,Cacheable,
+// ReadWrite,0x00,0xF00000,0xFFFFFF,0x00,0x100000,,,HOLE)
+
+ //
+ // PCI Memory Region ( TOLUD - 0xDFFFFFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,NonCacheable,
+ ReadWrite,0x00,0x00000000,0xDFFFFFFF,0x00,0xE0000000,,,PM01)
+
+ //
+ // PCI Memory Region ( TOUUD - (TOUUD + ABOVE_4G_MMIO_SIZE) )
+ // (This is dummy range for OS compatibility, will patch it in _CRS)
+ //
+ QWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,NonCacheable,
+ ReadWrite,0x00,0x10000,0x1FFFF,0x00,0x10000,,,PM02)
+
+ //
+ // PCH reserved resource ( 0xFD000000 - 0xFE7FFFFF )
+ //
+ DWordMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,NonCacheable,
+ ReadWrite,0x00,0xFD000000,0xFE7FFFFF,0x00,0x1800000,,,PM03)
+
+})
+
+Name(EP_B, 0) // to store EP BAR
+Name(MH_B, 0) // to store MCH BAR
+Name(PC_B, 0) // to store PCIe BAR
+Name(PC_L, 0) // to store PCIe BAR Length
+Name(DM_B, 0) // to store DMI BAR
+
+//
+// Get EP BAR
+//
+Method(GEPB,0,Serialized)
+{
+ if(LEqual(EP_B,0))
+ {
+ ShiftLeft(\_SB.PCI0.EPBR,12,EP_B)
+ }
+ Return(EP_B)
+}
+
+//
+// Get MCH BAR
+//
+Method(GMHB,0,Serialized)
+{
+ if(LEqual(MH_B,0))
+ {
+ ShiftLeft(\_SB.PCI0.MHBR,15,MH_B)
+ }
+ Return(MH_B)
+}
+
+//
+// Get PCIe BAR
+//
+Method(GPCB,0,Serialized)
+{
+ if(LEqual(PC_B,0))
+ {
+ ShiftLeft(\_SB.PCI0.PXBR,26,PC_B)
+ }
+ Return(PC_B)
+}
+
+//
+// Get PCIe Length
+//
+Method(GPCL,0,Serialized)
+{
+ if(LEqual(PC_L,0))
+ {
+ ShiftRight(0x10000000, \_SB.PCI0.PXSZ,PC_L)
+ }
+ Return(PC_L)
+}
+
+//
+// Get DMI BAR
+//
+Method(GDMB,0,Serialized)
+{
+ if(LEqual(DM_B,0))
+ {
+ ShiftLeft(\_SB.PCI0.DIBR,12,DM_B)
+ }
+ Return(DM_B)
+}
+
+
+Method(_CRS,0,Serialized)
+{
+ //
+ // Fix up Max Bus Number and Length
+ //
+ Store(\_SB.PCI0.GPCL(),Local0)
+ CreateWordField(BUF0, ^PB00._MAX, PBMX)
+ Store(Subtract(ShiftRight(Local0,20),2), PBMX)
+ CreateWordField(BUF0, ^PB00._LEN, PBLN)
+ Store(Subtract(ShiftRight(Local0,20),1), PBLN)
+ //
+ // Fix up all of the Option ROM areas from 0xC0000-0xFFFFF.
+ //
+ If(PM1L) // \_SB.PCI0
+ {
+ // PAMx != 0. Set length = 0.
+
+ CreateDwordField(BUF0, ^C000._LEN,C0LN)
+ Store(Zero,C0LN)
+ }
+
+ If(LEqual(PM1L,1))
+ {
+ CreateBitField(BUF0, ^C000._RW,C0RW)
+ Store(Zero,C0RW)
+ }
+
+ If(PM1H)
+ {
+ CreateDwordField(BUF0, ^C400._LEN,C4LN)
+ Store(Zero,C4LN)
+ }
+
+ If(LEqual(PM1H,1))
+ {
+ CreateBitField(BUF0, ^C400._RW,C4RW)
+ Store(Zero,C4RW)
+ }
+
+ If(PM2L)
+ {
+ CreateDwordField(BUF0, ^C800._LEN,C8LN)
+ Store(Zero,C8LN)
+ }
+
+ If(LEqual(PM2L,1))
+ {
+ CreateBitField(BUF0, ^C800._RW,C8RW)
+ Store(Zero,C8RW)
+ }
+
+ If(PM2H)
+ {
+ CreateDwordField(BUF0, ^CC00._LEN,CCLN)
+ Store(Zero,CCLN)
+ }
+
+ If(LEqual(PM2H,1))
+ {
+ CreateBitField(BUF0, ^CC00._RW,CCRW)
+ Store(Zero,CCRW)
+ }
+
+ If(PM3L)
+ {
+ CreateDwordField(BUF0, ^D000._LEN,D0LN)
+ Store(Zero,D0LN)
+ }
+
+ If(LEqual(PM3L,1))
+ {
+ CreateBitField(BUF0, ^D000._RW,D0RW)
+ Store(Zero,D0RW)
+ }
+
+ If(PM3H)
+ {
+ CreateDwordField(BUF0, ^D400._LEN,D4LN)
+ Store(Zero,D4LN)
+ }
+
+ If(LEqual(PM3H,1))
+ {
+ CreateBitField(BUF0, ^D400._RW,D4RW)
+ Store(Zero,D4RW)
+ }
+
+ If(PM4L)
+ {
+ CreateDwordField(BUF0, ^D800._LEN,D8LN)
+ Store(Zero,D8LN)
+ }
+
+ If(LEqual(PM4L,1))
+ {
+ CreateBitField(BUF0, ^D800._RW,D8RW)
+ Store(Zero,D8RW)
+ }
+
+ If(PM4H)
+ {
+ CreateDwordField(BUF0, ^DC00._LEN,DCLN)
+ Store(Zero,DCLN)
+ }
+
+ If(LEqual(PM4H,1))
+ {
+ CreateBitField(BUF0, ^DC00._RW,DCRW)
+ Store(Zero,DCRW)
+ }
+
+ If(PM5L)
+ {
+ CreateDwordField(BUF0, ^E000._LEN,E0LN)
+ Store(Zero,E0LN)
+ }
+
+ If(LEqual(PM5L,1))
+ {
+ CreateBitField(BUF0, ^E000._RW,E0RW)
+ Store(Zero,E0RW)
+ }
+
+ If(PM5H)
+ {
+ CreateDwordField(BUF0, ^E400._LEN,E4LN)
+ Store(Zero,E4LN)
+ }
+
+ If(LEqual(PM5H,1))
+ {
+ CreateBitField(BUF0, ^E400._RW,E4RW)
+ Store(Zero,E4RW)
+ }
+
+ If(PM6L)
+ {
+ CreateDwordField(BUF0, ^E800._LEN,E8LN)
+ Store(Zero,E8LN)
+ }
+
+ If(LEqual(PM6L,1))
+ {
+ CreateBitField(BUF0, ^E800._RW,E8RW)
+ Store(Zero,E8RW)
+ }
+
+ If(PM6H)
+ {
+ CreateDwordField(BUF0, ^EC00._LEN,ECLN)
+ Store(Zero,ECLN)
+ }
+
+ If(LEqual(PM6H,1))
+ {
+ CreateBitField(BUF0, ^EC00._RW,ECRW)
+ Store(Zero,ECRW)
+ }
+
+ If(PM0H)
+ {
+ CreateDwordField(BUF0, ^F000._LEN,F0LN)
+ Store(Zero,F0LN)
+ }
+
+ If(LEqual(PM0H,1))
+ {
+ CreateBitField(BUF0, ^F000._RW,F0RW)
+ Store(Zero,F0RW)
+ }
+
+ // Enable the 1MB region between 15-16MB if HENA = 1.
+ //
+ // If( MCHC.HENA)
+ // {
+ // CreateDwordField(BUF0, HOLE._LEN,H0LN)
+ // Store(0x100000,H0LN)
+ // }
+
+ //
+ // Create pointers to Memory Sizing values.
+ //
+ CreateDwordField(BUF0, ^PM01._MIN,M1MN)
+ CreateDwordField(BUF0, ^PM01._MAX,M1MX)
+ CreateDwordField(BUF0, ^PM01._LEN,M1LN)
+
+ //
+ // Set Memory Size Values. TLUD represents bits 31:20 of phyical
+ // TOM, so shift these bits into the correct position and fix up
+ // the Memory Region available to PCI.
+ //
+ Store (M32L, M1LN)
+ Store (M32B, M1MN)
+ Subtract (Add (M1MN, M1LN), 1, M1MX)
+
+ //
+ // Create pointers to Memory Sizing values.
+ // Patch PM02 range basing on memory size and OS type
+ //
+ If (LEqual(M64L, 0)) {
+ CreateQwordField(BUF0, ^PM02._LEN,MSLN)
+ //
+ // Set resource length to 0
+ //
+ Store (0, MSLN)
+ }
+ Else {
+ CreateQwordField(BUF0, ^PM02._LEN,M2LN)
+ CreateQwordField(BUF0, ^PM02._MIN,M2MN)
+ CreateQwordField(BUF0, ^PM02._MAX,M2MX)
+ //
+ // Set 64bit MMIO resource Base and Length
+ //
+ Store (M64L, M2LN)
+ Store (M64B, M2MN)
+ Subtract (Add (M2MN, M2LN), 1, M2MX)
+ }
+ Return(BUF0)
+}
+
+//
+//Name(GUID,UUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))
+//
+Name(GUID,Buffer(){0x5b, 0x4d, 0xdb, 0x33,
+ 0xf7, 0x1f,
+ 0x1c, 0x40,
+ 0x96, 0x57,
+ 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66})
+
+
+Name(SUPP,0) // PCI _OSC Support Field value
+Name(CTRL,0) // PCI _OSC Control Field value
+Name(XCNT, 0) // Variable used in _OSC for counting
+
+Method(_OSC,4,Serialized)
+{
+ //
+ // Check for proper UUID
+ // Save the capabilities buffer
+ //
+ Store(Arg3,Local0)
+
+ //
+ // Create DWord-adressable fields from the Capabilties Buffer
+ //
+ CreateDWordField(Local0,0,CDW1)
+ CreateDWordField(Local0,4,CDW2)
+ CreateDWordField(Local0,8,CDW3)
+
+
+ //
+ // Check for proper UUID
+ //
+ If(LEqual(Arg0,GUID))
+ {
+ // Save Capabilities DWord2 & 3
+ Store(CDW2,SUPP)
+ Store(CDW3,CTRL)
+
+ //
+ // You can clear bits in CTRL here if you don't want OS to take
+ // control
+ //
+ If(LNot(NEXP))
+ {
+ And(CTRL, 0xFFFFFFF8, CTRL) // disable Native hot plug, PME
+ }
+
+ If(LAnd(LEqual(TBTS, 1),LEqual(TNAT, 1)))
+ {
+ // \_OSC disallow only Advanced Error Reporting control
+ And(CTRL, 0xFFFFFFF7, CTRL)
+ }
+
+ If(Not(And(CDW1,1))) // Query flag clear?
+ { // Disable GPEs for features granted native control.
+ If(And(CTRL,0x01))
+ {
+ NHPG()
+ }
+ If(And(CTRL,0x04)) // PME control granted?
+ {
+ NPME()
+ }
+ }
+
+ If(LNotEqual(Arg1,One))
+ {
+ //
+ // Unknown revision
+ //
+ Or(CDW1,0x08,CDW1)
+ }
+
+ If(LNotEqual(CDW3,CTRL))
+ {
+ //
+ // Capabilities bits were masked
+ //
+ Or(CDW1,0x10,CDW1)
+ }
+ //
+ // Update DWORD3 in the buffer
+ //
+ Store(CTRL,CDW3)
+ Store(CTRL,OSCC)
+ Return(Local0)
+ } Else {
+ Or(CDW1,4,CDW1) // Unrecognized UUID
+ Return(Local0)
+ }
+} // End _OSC
+
+//
+// Added code for Dual IRQ support. Two set of ACPI IRQ tables were generated.
+// Code has been added to select the appropriate IRQ table by checking the CPUID.
+//
+Scope(\_SB.PCI0)
+{
+ Method(AR00) {
+ Return(\_SB.AR00)
+ }
+
+ Method(PR00) {
+ Return(\_SB.PR00)
+ }
+
+ Method(AR02) {
+ Return(\_SB.AR02)
+ }
+
+ Method(PR02) {
+ Return(\_SB.PR02)
+ }
+
+ Method(AR04) {
+ Return(\_SB.AR04)
+ }
+
+ Method(PR04) {
+ Return(\_SB.PR04)
+ }
+
+ Method(AR05) {
+ Return(\_SB.AR05)
+ }
+
+ Method(PR05) {
+ Return(\_SB.PR05)
+ }
+
+ Method(AR06) {
+ Return(\_SB.AR06)
+ }
+
+ Method(PR06) {
+ Return(\_SB.PR06)
+ }
+
+ Method(AR07) {
+ Return(\_SB.AR07)
+ }
+
+ Method(PR07) {
+ Return(\_SB.PR07)
+ }
+
+ Method(AR08) {
+ Return(\_SB.AR08)
+ }
+
+ Method(PR08) {
+ Return(\_SB.PR08)
+ }
+
+ Method(AR09) {
+ Return(\_SB.AR09)
+ }
+
+ Method(PR09) {
+ Return(\_SB.PR09)
+ }
+
+ Method(AR0A) {
+ Return(\_SB.AR0A)
+ }
+
+ Method(PR0A) {
+ Return(\_SB.PR0A)
+ }
+
+ Method(AR0B) {
+ Return(\_SB.AR0B)
+ }
+
+ Method(PR0B) {
+ Return(\_SB.PR0B)
+ }
+
+ //
+ // I.G.D
+ //
+ Device(GFX0) {
+ Name(_ADR, 0x00020000)
+ }
+
+ //
+ // Device ISP0 is the ISP PCI device
+ //
+ Device(ISP0) {
+ Name(_ADR, 0x00050000)
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaAcpiTables.inf b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaAcpiTables.inf
new file mode 100644
index 0000000000..ff39573378
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaAcpiTables.inf
@@ -0,0 +1,61 @@
+## @file
+# Component description file for the ACPI tables
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+
+[Defines]
+INF_VERSION = 0x00010005
+BASE_NAME = SaAcpiTables
+FILE_GUID = 3c0ed5e2-91ea-4b94-820d-9daf9a3bb4a2
+MODULE_TYPE = USER_DEFINED
+VERSION_STRING = 1.0
+
+[Sources]
+ Dmar/Dmar.aslc
+ Dmar/Dmar.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+[Pcd]
+
+[Protocols]
+
+[PPIs]
+
+[Guids]
+
+[Depex]
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Igfx.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Igfx.asl
new file mode 100644
index 0000000000..c853700c40
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Igfx.asl
@@ -0,0 +1,1782 @@
+/** @file
+ This file contains the IGD OpRegion/Software ACPI Reference
+ Code.
+ It defines the methods to enable/disable output switching,
+ store display switching and LCD brightness BIOS control
+ and return valid addresses for all display device encoders
+ present in the system, etc.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+External(\ECST, MethodObj)
+External(\ECON, IntObj)
+External(OSYS, IntObj)
+External(CPSC)
+External(\GUAM, MethodObj)
+External(DSEN)
+External(S0ID)
+
+// Enable/Disable Output Switching. In WIN2K/WINXP, _DOS = 0 will
+// get called during initialization to prepare for an ACPI Display
+// Switch Event. During an ACPI Display Switch, the OS will call
+// _DOS = 2 immediately after a Notify=0x80 to temporarily disable
+// all Display Switching. After ACPI Display Switching is complete,
+// the OS will call _DOS = 0 to re-enable ACPI Display Switching.
+Method(_DOS,1)
+{
+ //
+ // Store Display Switching and LCD brightness BIOS control bit
+ //
+ Store(And(Arg0,7),DSEN)
+}
+
+//
+// Enumerate the Display Environment. This method will return
+// valid addresses for all display device encoders present in the
+// system. The Miniport Driver will reject the addresses for every
+// encoder that does not have an attached display device. After
+// enumeration is complete, the OS will call the _DGS methods
+// during a display switch only for the addresses accepted by the
+// Miniport Driver. For hot-insertion and removal of display
+// devices, a re-enumeration notification will be required so the
+// address of the newly present display device will be accepted by
+// the Miniport Driver.
+//
+Method(_DOD,0)
+{
+ If (LEqual(IMTP,1)) {
+ //
+ // Increment number of devices if iMGU is enabled
+ //
+ Store(1, NDID)
+ } Else {
+ Store(0, NDID)
+ }
+
+ If(LNotEqual(DIDL, Zero))
+ {
+ Store(SDDL(DIDL),DID1)
+ }
+ If(LNotEqual(DDL2, Zero))
+ {
+ Store(SDDL(DDL2),DID2)
+ }
+ If(LNotEqual(DDL3, Zero))
+ {
+ Store(SDDL(DDL3),DID3)
+ }
+ If(LNotEqual(DDL4, Zero))
+ {
+ Store(SDDL(DDL4),DID4)
+ }
+ If(LNotEqual(DDL5, Zero))
+ {
+ Store(SDDL(DDL5),DID5)
+ }
+ If(LNotEqual(DDL6, Zero))
+ {
+ Store(SDDL(DDL6),DID6)
+ }
+ If(LNotEqual(DDL7, Zero))
+ {
+ Store(SDDL(DDL7),DID7)
+ }
+ If(LNotEqual(DDL8, Zero))
+ {
+ Store(SDDL(DDL8),DID8)
+ }
+ If(LNotEqual(DDL9, Zero))
+ {
+ Store(SDDL(DDL9),DID9)
+ }
+ If(LNotEqual(DD10, Zero))
+ {
+ Store(SDDL(DD10),DIDA)
+ }
+ If(LNotEqual(DD11, Zero))
+ {
+ Store(SDDL(DD11),DIDB)
+ }
+ If(LNotEqual(DD12, Zero))
+ {
+ Store(SDDL(DD12),DIDC)
+ }
+ If(LNotEqual(DD13, Zero))
+ {
+ Store(SDDL(DD13),DIDD)
+ }
+ If(LNotEqual(DD14, Zero))
+ {
+ Store(SDDL(DD14),DIDE)
+ }
+ If(LNotEqual(DD15, Zero))
+ {
+ Store(SDDL(DD15),DIDF)
+ }
+
+ //
+ // Enumerate the encoders. Note that for
+ // current silicon, the maximum number of encoders
+ // possible is 15.
+ //
+ If(LEqual(NDID,1))
+ {
+ Name(TMP1,Package() {
+ 0xFFFFFFFF})
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP1,0))
+ } Else {
+ Store(Or(0x10000,DID1),Index(TMP1,0))
+ }
+ Return(TMP1)
+ }
+
+ If(LEqual(NDID,2))
+ {
+ Name(TMP2,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP2,0))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP2,1))
+ } Else {
+ Store(Or(0x10000,DID2),Index(TMP2,1))
+ }
+ Return(TMP2)
+ }
+
+ If(LEqual(NDID,3))
+ {
+ Name(TMP3,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP3,0))
+ Store(Or(0x10000,DID2),Index(TMP3,1))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP3,2))
+ } Else {
+ Store(Or(0x10000,DID3),Index(TMP3,2))
+ }
+ Return(TMP3)
+ }
+
+ If(LEqual(NDID,4))
+ {
+ Name(TMP4,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP4,0))
+ Store(Or(0x10000,DID2),Index(TMP4,1))
+ Store(Or(0x10000,DID3),Index(TMP4,2))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP4,3))
+ } Else {
+ Store(Or(0x10000,DID4),Index(TMP4,3))
+ }
+ Return(TMP4)
+ }
+
+ If(LEqual(NDID,5))
+ {
+ Name(TMP5,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP5,0))
+ Store(Or(0x10000,DID2),Index(TMP5,1))
+ Store(Or(0x10000,DID3),Index(TMP5,2))
+ Store(Or(0x10000,DID4),Index(TMP5,3))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP5,4))
+ } Else {
+ Store(Or(0x10000,DID5),Index(TMP5,4))
+ }
+ Return(TMP5)
+ }
+
+ If(LEqual(NDID,6))
+ {
+ Name(TMP6,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP6,0))
+ Store(Or(0x10000,DID2),Index(TMP6,1))
+ Store(Or(0x10000,DID3),Index(TMP6,2))
+ Store(Or(0x10000,DID4),Index(TMP6,3))
+ Store(Or(0x10000,DID5),Index(TMP6,4))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP6,5))
+ } Else {
+ Store(Or(0x10000,DID6),Index(TMP6,5))
+ }
+ Return(TMP6)
+ }
+
+ If(LEqual(NDID,7))
+ {
+ Name(TMP7,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP7,0))
+ Store(Or(0x10000,DID2),Index(TMP7,1))
+ Store(Or(0x10000,DID3),Index(TMP7,2))
+ Store(Or(0x10000,DID4),Index(TMP7,3))
+ Store(Or(0x10000,DID5),Index(TMP7,4))
+ Store(Or(0x10000,DID6),Index(TMP7,5))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP7,6))
+ } Else {
+ Store(Or(0x10000,DID7),Index(TMP7,6))
+ }
+ Return(TMP7)
+ }
+
+ If(LEqual(NDID,8))
+ {
+ Name(TMP8,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP8,0))
+ Store(Or(0x10000,DID2),Index(TMP8,1))
+ Store(Or(0x10000,DID3),Index(TMP8,2))
+ Store(Or(0x10000,DID4),Index(TMP8,3))
+ Store(Or(0x10000,DID5),Index(TMP8,4))
+ Store(Or(0x10000,DID6),Index(TMP8,5))
+ Store(Or(0x10000,DID7),Index(TMP8,6))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP8,7))
+ } Else {
+ Store(Or(0x10000,DID8),Index(TMP8,7))
+ }
+ Return(TMP8)
+ }
+
+ If(LEqual(NDID,9))
+ {
+ Name(TMP9,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP9,0))
+ Store(Or(0x10000,DID2),Index(TMP9,1))
+ Store(Or(0x10000,DID3),Index(TMP9,2))
+ Store(Or(0x10000,DID4),Index(TMP9,3))
+ Store(Or(0x10000,DID5),Index(TMP9,4))
+ Store(Or(0x10000,DID6),Index(TMP9,5))
+ Store(Or(0x10000,DID7),Index(TMP9,6))
+ Store(Or(0x10000,DID8),Index(TMP9,7))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMP9,8))
+ } Else {
+ Store(Or(0x10000,DID9),Index(TMP9,8))
+ }
+ Return(TMP9)
+ }
+
+ If(LEqual(NDID,0x0A))
+ {
+ Name(TMPA,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPA,0))
+ Store(Or(0x10000,DID2),Index(TMPA,1))
+ Store(Or(0x10000,DID3),Index(TMPA,2))
+ Store(Or(0x10000,DID4),Index(TMPA,3))
+ Store(Or(0x10000,DID5),Index(TMPA,4))
+ Store(Or(0x10000,DID6),Index(TMPA,5))
+ Store(Or(0x10000,DID7),Index(TMPA,6))
+ Store(Or(0x10000,DID8),Index(TMPA,7))
+ Store(Or(0x10000,DID9),Index(TMPA,8))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMPA,9))
+ } Else {
+ Store(Or(0x10000,DIDA),Index(TMPA,9))
+ }
+ Return(TMPA)
+ }
+
+ If(LEqual(NDID,0x0B))
+ {
+ Name(TMPB,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPB,0))
+ Store(Or(0x10000,DID2),Index(TMPB,1))
+ Store(Or(0x10000,DID3),Index(TMPB,2))
+ Store(Or(0x10000,DID4),Index(TMPB,3))
+ Store(Or(0x10000,DID5),Index(TMPB,4))
+ Store(Or(0x10000,DID6),Index(TMPB,5))
+ Store(Or(0x10000,DID7),Index(TMPB,6))
+ Store(Or(0x10000,DID8),Index(TMPB,7))
+ Store(Or(0x10000,DID9),Index(TMPB,8))
+ Store(Or(0x10000,DIDA),Index(TMPB,9))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMPB,10))
+ } Else {
+ Store(Or(0x10000,DIDB),Index(TMPB,10))
+ }
+ Return(TMPB)
+ }
+
+ If(LEqual(NDID,0x0C))
+ {
+ Name(TMPC,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPC,0))
+ Store(Or(0x10000,DID2),Index(TMPC,1))
+ Store(Or(0x10000,DID3),Index(TMPC,2))
+ Store(Or(0x10000,DID4),Index(TMPC,3))
+ Store(Or(0x10000,DID5),Index(TMPC,4))
+ Store(Or(0x10000,DID6),Index(TMPC,5))
+ Store(Or(0x10000,DID7),Index(TMPC,6))
+ Store(Or(0x10000,DID8),Index(TMPC,7))
+ Store(Or(0x10000,DID9),Index(TMPC,8))
+ Store(Or(0x10000,DIDA),Index(TMPC,9))
+ Store(Or(0x10000,DIDB),Index(TMPC,10))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMPC,11))
+ } Else {
+ Store(Or(0x10000,DIDC),Index(TMPC,11))
+ }
+ Return(TMPC)
+ }
+
+ If(LEqual(NDID,0x0D))
+ {
+ Name(TMPD,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPD,0))
+ Store(Or(0x10000,DID2),Index(TMPD,1))
+ Store(Or(0x10000,DID3),Index(TMPD,2))
+ Store(Or(0x10000,DID4),Index(TMPD,3))
+ Store(Or(0x10000,DID5),Index(TMPD,4))
+ Store(Or(0x10000,DID6),Index(TMPD,5))
+ Store(Or(0x10000,DID7),Index(TMPD,6))
+ Store(Or(0x10000,DID8),Index(TMPD,7))
+ Store(Or(0x10000,DID9),Index(TMPD,8))
+ Store(Or(0x10000,DIDA),Index(TMPD,9))
+ Store(Or(0x10000,DIDB),Index(TMPD,10))
+ Store(Or(0x10000,DIDC),Index(TMPD,11))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMPD,12))
+ } Else {
+ Store(Or(0x10000,DIDD),Index(TMPD,12))
+ }
+ Return(TMPD)
+ }
+
+ If(LEqual(NDID,0x0E))
+ {
+ Name(TMPE,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPE,0))
+ Store(Or(0x10000,DID2),Index(TMPE,1))
+ Store(Or(0x10000,DID3),Index(TMPE,2))
+ Store(Or(0x10000,DID4),Index(TMPE,3))
+ Store(Or(0x10000,DID5),Index(TMPE,4))
+ Store(Or(0x10000,DID6),Index(TMPE,5))
+ Store(Or(0x10000,DID7),Index(TMPE,6))
+ Store(Or(0x10000,DID8),Index(TMPE,7))
+ Store(Or(0x10000,DID9),Index(TMPE,8))
+ Store(Or(0x10000,DIDA),Index(TMPE,9))
+ Store(Or(0x10000,DIDB),Index(TMPE,10))
+ Store(Or(0x10000,DIDC),Index(TMPE,11))
+ Store(Or(0x10000,DIDD),Index(TMPE,12))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMPE,13))
+ } Else {
+ Store(Or(0x10000,DIDE),Index(TMPE,13))
+ }
+ Return(TMPE)
+ }
+
+ If(LEqual(NDID,0x0F))
+ {
+ Name(TMPF,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPF,0))
+ Store(Or(0x10000,DID2),Index(TMPF,1))
+ Store(Or(0x10000,DID3),Index(TMPF,2))
+ Store(Or(0x10000,DID4),Index(TMPF,3))
+ Store(Or(0x10000,DID5),Index(TMPF,4))
+ Store(Or(0x10000,DID6),Index(TMPF,5))
+ Store(Or(0x10000,DID7),Index(TMPF,6))
+ Store(Or(0x10000,DID8),Index(TMPF,7))
+ Store(Or(0x10000,DID9),Index(TMPF,8))
+ Store(Or(0x10000,DIDA),Index(TMPF,9))
+ Store(Or(0x10000,DIDB),Index(TMPF,10))
+ Store(Or(0x10000,DIDC),Index(TMPF,11))
+ Store(Or(0x10000,DIDD),Index(TMPF,12))
+ Store(Or(0x10000,DIDE),Index(TMPF,13))
+ If (LEqual(IMTP,1)) {
+ //
+ // IGFX need report ISP0 as GFX0 child
+ //
+ Store(0x0002CA00,Index(TMPF,14))
+ } Else {
+ Store(Or(0x10000,DIDF),Index(TMPF,14))
+ }
+ Return(TMPF)
+ }
+
+ If(LEqual(NDID,0x10))
+ {
+ Name(TMPG,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPG,0))
+ Store(Or(0x10000,DID2),Index(TMPG,1))
+ Store(Or(0x10000,DID3),Index(TMPG,2))
+ Store(Or(0x10000,DID4),Index(TMPG,3))
+ Store(Or(0x10000,DID5),Index(TMPG,4))
+ Store(Or(0x10000,DID6),Index(TMPG,5))
+ Store(Or(0x10000,DID7),Index(TMPG,6))
+ Store(Or(0x10000,DID8),Index(TMPG,7))
+ Store(Or(0x10000,DID9),Index(TMPG,8))
+ Store(Or(0x10000,DIDA),Index(TMPG,9))
+ Store(Or(0x10000,DIDB),Index(TMPG,10))
+ Store(Or(0x10000,DIDC),Index(TMPG,11))
+ Store(Or(0x10000,DIDD),Index(TMPG,12))
+ Store(Or(0x10000,DIDE),Index(TMPG,13))
+ Store(Or(0x10000,DIDF),Index(TMPG,14))
+ //
+ // IGFX need report ISP0 as GFX0 child
+ // NDID can only be 0x10 if IMGU is enabled
+ //
+ Store(0x0002CA00,Index(TMPG,15))
+ Return(TMPG)
+ }
+
+ //
+ // If nothing else, return Unknown LFP.
+ // (Prevents compiler warning.)
+ //
+ Return(Package() {0x00000400})
+}
+
+Device(DD01)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID1),0x400))
+ {
+ Store(0x1, EDPV)
+ Store(NXD1, NXDX)
+ Store(DID1, DIDX)
+ Return(1)
+ }
+ If(LEqual(DID1,0))
+ {
+ Return(1)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID1))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ Return(CDDS(DID1))
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD1)
+ }
+ Return(NDDS(DID1))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD02)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID2),0x400))
+ {
+ Store(0x2, EDPV)
+ Store(NXD2, NXDX)
+ Store(DID2, DIDX)
+ Return(2)
+ }
+ If(LEqual(DID2,0))
+ {
+ Return(2)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID2))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(LIDS,0))
+ {
+ Return(0x0)
+ }
+ Return(CDDS(DID2))
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ //
+ // Return the Next State.
+ //
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD2)
+ }
+ Return(NDDS(DID2))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD03)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID3),0x400))
+ {
+ Store(0x3, EDPV)
+ Store(NXD3, NXDX)
+ Store(DID3, DIDX)
+ Return(3)
+ }
+ If(LEqual(DID3,0))
+ {
+ Return(3)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID3))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID3,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID3))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD3)
+ }
+ Return(NDDS(DID3))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD04)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID4),0x400))
+ {
+ Store(0x4, EDPV)
+ Store(NXD4, NXDX)
+ Store(DID4, DIDX)
+ Return(4)
+ }
+ If(LEqual(DID4,0))
+ {
+ Return(4)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID4))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID4,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID4))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD4)
+ }
+ Return(NDDS(DID4))
+ }
+
+ //
+ // Device Set State. (See table above.)
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD05)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID5),0x400))
+ {
+ Store(0x5, EDPV)
+ Store(NXD5, NXDX)
+ Store(DID5, DIDX)
+ Return(5)
+ }
+ If(LEqual(DID5,0))
+ {
+ Return(5)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID5))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID5,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID5))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD5)
+ }
+ Return(NDDS(DID5))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD06)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID6),0x400))
+ {
+ Store(0x6, EDPV)
+ Store(NXD6, NXDX)
+ Store(DID6, DIDX)
+ Return(6)
+ }
+ If(LEqual(DID6,0))
+ {
+ Return(6)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID6))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID6,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID6))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD6)
+ }
+ Return(NDDS(DID6))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD07)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID7),0x400))
+ {
+ Store(0x7, EDPV)
+ Store(NXD7, NXDX)
+ Store(DID7, DIDX)
+ Return(7)
+ }
+ If(LEqual(DID7,0))
+ {
+ Return(7)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID7))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID7,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID7))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD7)
+ }
+ Return(NDDS(DID7))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD08)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID8),0x400))
+ {
+ Store(0x8, EDPV)
+ Store(NXD8, NXDX)
+ Store(DID8, DIDX)
+ Return(8)
+ }
+ If(LEqual(DID8,0))
+ {
+ Return(8)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID8))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID8,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID8))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DID8))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD09)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID9),0x400))
+ {
+ Store(0x9, EDPV)
+ Store(NXD8, NXDX)
+ Store(DID9, DIDX)
+ Return(9)
+ }
+ If(LEqual(DID9,0))
+ {
+ Return(9)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID9))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID9,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID9))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DID9))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0A)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDA),0x400))
+ {
+ Store(0xA, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDA, DIDX)
+ Return(0x0A)
+ }
+ If(LEqual(DIDA,0))
+ {
+ Return(0x0A)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDA))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDA,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DIDA))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDA))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0B)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDB),0x400))
+ {
+ Store(0xB, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDB, DIDX)
+ Return(0X0B)
+ }
+ If(LEqual(DIDB,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDB))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDB,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DIDB))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDB))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0C)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDC),0x400))
+ {
+ Store(0xC, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDC, DIDX)
+ Return(0X0C)
+ }
+ If(LEqual(DIDC,0))
+ {
+ Return(0x0C)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDC))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDC,0))
+ {
+ Return(0x0C)
+ }
+ Else
+ {
+ Return(CDDS(DIDC))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDC))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0D)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDD),0x400))
+ {
+ Store(0xD, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDD, DIDX)
+ Return(0X0D)
+ }
+ If(LEqual(DIDD,0))
+ {
+ Return(0x0D)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDD))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDD,0))
+ {
+ Return(0x0D)
+ }
+ Else
+ {
+ Return(CDDS(DIDD))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDD))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0E)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDE),0x400))
+ {
+ Store(0xE, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDE, DIDX)
+ Return(0X0E)
+ }
+ If(LEqual(DIDE,0))
+ {
+ Return(0x0E)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDE))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDE,0))
+ {
+ Return(0x0E)
+ }
+ Else
+ {
+ Return(CDDS(DIDE))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDE))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0F)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDF),0x400))
+ {
+ Store(0xF, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDF, DIDX)
+ Return(0X0F)
+ }
+ If(LEqual(DIDF,0))
+ {
+ Return(0x0F)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDF))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDC,0))
+ {
+ Return(0x0F)
+ }
+ Else
+ {
+ Return(CDDS(DIDF))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDF))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+//
+//Device for eDP
+//
+Device(DD1F)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(EDPV, 0x0))
+ {
+ Return(0x1F)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDX))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(EDPV, 0x0))
+ {
+ Return(0x00)
+ }
+ Else
+ {
+ Return(CDDS(DIDX))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(SGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXDX)
+ }
+ Return(NDDS(DIDX))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+
+ //
+ // Query List of Brightness Control Levels Supported.
+ //
+ Method(_BCL,0)
+ {
+ //
+ // List of supported brightness levels in the following sequence.
+ // Level when machine has full power.
+ // Level when machine is on batteries.
+ // Other supported levels.
+ //
+ Return(Package(){80, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100})
+ }
+
+ //
+ // Set the Brightness Level.
+ //
+ Method (_BCM,1)
+ {
+ //
+ // Set the requested level if it is between 0 and 100%.
+ //
+ If(LAnd(LGreaterEqual(Arg0,0),LLessEqual(Arg0,100)))
+ {
+ \_SB.PCI0.GFX0.AINT(1, Arg0)
+ Store(Arg0,BRTL) // Store Brightness Level.
+ }
+ }
+
+ //
+ // Brightness Query Current level.
+ //
+ Method (_BQC,0)
+ {
+ Return(BRTL)
+ }
+}
+
+Method(SDDL,1)
+{
+ Increment(NDID)
+ Store(And(Arg0,0xF0F),Local0)
+ Or(0x80000000,Local0, Local1)
+ If(LEqual(DIDL,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL2,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL3,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL4,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL5,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL6,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL7,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL8,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL9,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD10,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD11,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD12,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD13,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD14,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD15,Local0))
+ {
+ Return(Local1)
+ }
+ Return(0)
+}
+
+Method(CDDS,1)
+{
+ Store(And(Arg0,0xF0F),Local0)
+
+ If(LEqual(0, Local0))
+ {
+ Return(0x1D)
+ }
+ If(LEqual(CADL, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL2, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL3, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL4, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL5, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL6, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL7, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL8, Local0))
+ {
+ Return(0x1F)
+ }
+ Return(0x1D)
+}
+
+Method(NDDS,1)
+{
+ Store(And(Arg0,0xF0F),Local0)
+
+ If(LEqual(0, Local0))
+ {
+ Return(0)
+ }
+ If(LEqual(NADL, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL2, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL3, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL4, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL5, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL6, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL7, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL8, Local0))
+ {
+ Return(1)
+ }
+ Return(0)
+}
+
+//
+// Device Set State Table
+// BIT31 BIT30 Execution
+// 0 0 Don't implement.
+// 0 1 Cache change. Nothing to Implement.
+// 1 0 Don't Implement.
+// 1 1 Display Switch Complete. Implement.
+//
+Method(DSST,1)
+{
+ If(LEqual(And(Arg0,0xC0000000),0xC0000000))
+ {
+ //
+ // State change was performed by the
+ // Video Drivers. Simply update the
+ // New State.
+ //
+ Store(NSTE,CSTE)
+ }
+}
+
+//
+// Include IGD OpRegion/Software SCI interrupt handler/DSM which is used by
+// the graphics drivers to request data from system BIOS.
+//
+include ("IgfxOpRn.asl")
+include ("IgfxDsm.asl")
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxCommon.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxCommon.asl
new file mode 100644
index 0000000000..4d28ad0068
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxCommon.asl
@@ -0,0 +1,487 @@
+/** @file
+ IGD OpRegion/Software SCI Reference Code.
+ This file contains ASL code with the purpose of handling events
+ i.e. hotkeys and other system interrupts.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+//
+// Notes:
+// 1. The following routines are to be called from the appropriate event
+// handlers.
+// 2. This code cannot comprehend the exact implementation in the OEM's BIOS.
+// Therefore, an OEM must call these methods from the existing event
+// handler infrastructure. Details on when/why to call each method is
+// included in the method header under the "usage" section.
+//
+
+/************************************************************************;
+;* ACPI Notification Methods
+;************************************************************************/
+
+
+/************************************************************************;
+;*
+;* Name: PDRD
+;*
+;* Description: Check if the graphics driver is ready to process
+;* notifications and video extensions.
+;*
+;* Usage: This method is to be called prior to performing any
+;* notifications or handling video extensions.
+;* Ex: If (PDRD()) {Return (FAIL)}
+;*
+;* Input: None
+;*
+;* Output: None
+;*
+;* References: DRDY (Driver ready status), ASLP (Driver recommended
+;* sleep timeout value).
+;*
+;************************************************************************/
+
+External(HNOT, MethodObj)
+
+Method(PDRD)
+{
+ //
+ // If DRDY is clear, the driver is not ready. If the return value is
+ // !=0, do not perform any notifications or video extension handling.
+ //
+ Return(LNot(DRDY))
+}
+
+/************************************************************************;
+;*
+;* Name: PSTS
+;*
+;* Description: Check if the graphics driver has completed the previous
+;* "notify" command.
+;*
+;* Usage: This method is called before every "notify" command. A
+;* "notify" should only be set if the driver has completed the
+;* previous command. Else, ignore the event and exit the parent
+;* method.
+;* Ex: If (PSTS()) {Return (FAIL)}
+;*
+;* Input: None
+;*
+;* Output: None
+;*
+;* References: CSTS (Notification status), ASLP (Driver recommended sleep
+;* timeout value).
+;*
+;************************************************************************/
+
+Method(PSTS)
+{
+ If(LGreater(CSTS, 2))
+ {
+ //
+ // Sleep for ASLP milliseconds if the status is not "success,
+ // failure, or pending"
+ //
+ Sleep(ASLP)
+ }
+
+ Return(LEqual(CSTS, 3)) // Return True if still Dispatched
+}
+
+/************************************************************************;
+;*
+;* Name: GNOT
+;*
+;* Description: Call the appropriate methods to query the graphics driver
+;* status. If all methods return success, do a notification of
+;* the graphics device.
+;*
+;* Usage: This method is to be called when a graphics device
+;* notification is required (display switch hotkey, etc).
+;*
+;* Input: Arg0 = Current event type:
+;* 1 = display switch
+;* 2 = lid
+;* 3 = dock
+;* Arg1 = Notification type:
+;* 0 = Re-enumeration
+;* 0x80 = Display switch
+;*
+;* Output: Returns 0 = success, 1 = failure
+;*
+;* References: PDRD and PSTS methods. OSYS (OS version)
+;*
+;************************************************************************/
+
+Method(GNOT, 2)
+{
+ //
+ // Check for 1. Driver loaded, 2. Driver ready.
+ // If any of these cases is not met, skip this event and return failure.
+ //
+ If(PDRD())
+ {
+ Return(0x1) // Return failure if driver not loaded.
+ }
+
+ Store(Arg0, CEVT) // Set up the current event value
+ Store(3, CSTS) // CSTS=BIOS dispatched an event
+
+ If(LAnd(LEqual(CHPD, 0), LEqual(Arg1, 0))) // Do not re-enum if driver supports hotplug
+ {
+ //
+ // Re-enumerate the Graphics Device for non-XP operating systems.
+ //
+ Notify(\_SB.PCI0.GFX0, Arg1)
+ }
+
+ If(CondRefOf(HNOT))
+ {
+ HNOT(Arg0) //Notification handler for Switchable graphics
+ }
+ Else
+ {
+ Notify(\_SB.PCI0.GFX0,0x80)
+ }
+
+ Return(0x0) // Return success
+}
+
+/************************************************************************;
+;*
+;* Name: GHDS
+;*
+;* Description: Handle a hotkey display switching event (performs a
+;* Notify(GFX0, 0).
+;*
+;* Usage: This method must be called when a hotkey event occurs and the
+;* purpose of that hotkey is to do a display switch.
+;*
+;* Input: Arg0 = Toggle table number.
+;*
+;* Output: Returns 0 = success, 1 = failure.
+;* CEVT and TIDX are indirect outputs.
+;*
+;* References: TIDX, GNOT
+;*
+;************************************************************************/
+
+Method(GHDS, 1)
+{
+ Store(Arg0, TIDX) // Store the table number
+ //
+ // Call GNOT for CEVT = 1 = hotkey, notify value = 0
+ //
+ Return(GNOT(1, 0)) // Return stats from GNOT
+}
+
+/************************************************************************;
+;*
+;* Name: GLID
+;*
+;* Description: Handle a lid event (performs the Notify(GFX0, 0), but not the
+;* lid notify).
+;*
+;* Usage: This method must be called when a lid event occurs. A
+;* Notify(LID0, 0x80) must follow the call to this method.
+;*
+;* Input: Arg0 = Lid state:
+;* 0 = All closed
+;* 1 = internal LFP lid open
+;* 2 = external lid open
+;* 3 = both external and internal open
+;*
+;* Output: Returns 0=success, 1=failure.
+;* CLID and CEVT are indirect outputs.
+;*
+;* References: CLID, GNOT
+;*
+;************************************************************************/
+
+Method(GLID, 1)
+{
+
+ If (LEqual(Arg0,1))
+ {
+ Store(3,CLID)
+ }
+ Else
+ {
+ Store(Arg0, CLID)
+ }
+ //
+ //Store(Arg0, CLID) // Store the current lid state
+ // Call GNOT for CEVT=2=Lid, notify value = 0
+ //
+ if (GNOT(2, 0)) {
+ Or (CLID, 0x80000000, CLID)
+ Return (1) // Return Fail
+ }
+
+ Return (0) // Return Pass
+}
+
+/************************************************************************;
+;*
+;* Name: GDCK
+;*
+;* Description: Handle a docking event by updating the current docking status
+;* and doing a notification.
+;*
+;* Usage: This method must be called when a docking event occurs.
+;*
+;* Input: Arg0 = Docking state:
+;* 0 = Undocked
+;* 1 = Docked
+;*
+;* Output: Returns 0=success, 1=failure.
+;* CDCK and CEVT are indirect outputs.
+;*
+;* References: CDCK, GNOT
+;*
+;************************************************************************/
+
+Method(GDCK, 1)
+{
+ Store(Arg0, CDCK) // Store the current dock state
+ //
+ // Call GNOT for CEVT=4=Dock, notify value = 0
+ //
+ Return(GNOT(4, 0)) // Return stats from GNOT
+}
+
+/************************************************************************;
+;* ASLE Interrupt Methods
+;************************************************************************/
+
+/************************************************************************;
+;*
+;* Name: PARD
+;*
+;* Description: Check if the driver is ready to handle ASLE interrupts
+;* generate by the system BIOS.
+;*
+;* Usage: This method must be called before generating each ASLE
+;* interrupt.
+;*
+;* Input: None
+;*
+;* Output: Returns 0 = success, 1 = failure.
+;*
+;* References: ARDY (Driver readiness), ASLP (Driver recommended sleep
+;* timeout value)
+;*
+;************************************************************************/
+
+Method(PARD)
+{
+ If(LNot(ARDY))
+ {
+ //
+ // Sleep for ASLP milliseconds if the driver is not ready.
+ //
+ Sleep(ASLP)
+ }
+ //
+ // If ARDY is clear, the driver is not ready. If the return value is
+ // !=0, do not generate the ASLE interrupt.
+ //
+ Return(LNot(ARDY))
+}
+
+//
+// Intel Ultrabook Event Handler. Arg0 represents the Ultrabook Event Bit # to pass
+// to the Intel Graphics Driver. Note that this is a serialized method, meaning
+// sumultaneous events are not allowed.
+//
+Method(IUEH,1,Serialized)
+{
+ And(IUER,0xC0,IUER) // Clear all button events on entry.
+ XOr(IUER,Shiftleft(1,Arg0),IUER) // Toggle status.
+
+ If(LLessEqual(Arg0,4)) // Button Event?
+ {
+ Return(AINT(5,0)) // Generate event and return status.
+
+ }
+ Else // Indicator Event.
+ {
+ Return(AINT(Arg0,0)) // Generate event and return status.
+ }
+}
+
+/************************************************************************;
+;*
+;* Name: AINT
+;*
+;* Description: Call the appropriate methods to generate an ASLE interrupt.
+;* This process includes ensuring the graphics driver is ready
+;* to process the interrupt, ensuring the driver supports the
+;* interrupt of interest, and passing information about the event
+;* to the graphics driver.
+;*
+;* Usage: This method must called to generate an ASLE interrupt.
+;*
+;* Input: Arg0 = ASLE command function code:
+;* 0 = Set ALS illuminance
+;* 1 = Set backlight brightness
+;* 2 = Do Panel Fitting
+;* 4 = Reserved
+;* 5 = Button Indicator Event
+;* 6 = Convertible Indicator Event
+;* 7 = Docking Indicator Event
+;* Arg1 = If Arg0 = 0, current ALS reading:
+;* 0 = Reading below sensor range
+;* 1-0xFFFE = Current sensor reading
+;* 0xFFFF = Reading above sensor range
+;* Arg1 = If Arg0 = 1, requested backlight percentage
+;*
+;* Output: Returns 0 = success, 1 = failure
+;*
+;* References: PARD method.
+;*
+;************************************************************************/
+
+Method(AINT, 2)
+{
+ //
+ // Return failure if the requested feature is not supported by the
+ // driver.
+ //
+ If(LNot(And(TCHE, ShiftLeft(1, Arg0))))
+ {
+ Return(0x1)
+ }
+ //
+ // Return failure if the driver is not ready to handle an ASLE
+ // interrupt.
+ //
+ If(PARD())
+ {
+ Return(0x1)
+ }
+ //
+ // Handle Intel Ultrabook Events.
+ //
+ If(LAnd(LGreaterEqual(Arg0,5),LLessEqual(Arg0,7)))
+ {
+ Store(ShiftLeft(1,Arg0), ASLC) // Set Ultrbook Event [6:4].
+ Store(0x01, ASLE) // Generate ASLE interrupt
+
+ Store(0,Local2) // Use Local2 as a timeout counter. Intialize to zero.
+
+ While(LAnd(LLess(Local2,250),LNotEqual(ASLC,0))) // Wait 1 second or until Driver ACKs a success.
+ {
+ Sleep(4) // Delay 4 ms.
+ Increment(Local2) // Increment Timeout.
+ }
+
+ Return(0) // Return success
+ }
+ //
+ // Evaluate the first argument (Panel fitting, backlight brightness, or ALS).
+ //
+ If(LEqual(Arg0, 2)) // Arg0 = 2, so request a panel fitting mode change.
+ {
+ If(CPFM) // If current mode field is non-zero use it.
+ {
+ And(CPFM, 0x0F, Local0) // Create variables without reserved
+ And(EPFM, 0x0F, Local1) // or valid bits.
+
+ If(LEqual(Local0, 1)) // If current mode is centered,
+ {
+ If(And(Local1, 6)) // and if stretched is enabled,
+ {
+ Store(6, PFIT) // request stretched.
+ }
+ Else // Otherwise,
+ {
+ If(And(Local1, 8)) // if aspect ratio is enabled,
+ {
+ Store(8, PFIT) // request aspect ratio.
+ }
+ Else // Only centered mode is enabled
+ {
+ Store(1, PFIT) // so request centered. (No change.)
+ }
+ }
+ }
+ If(LEqual(Local0, 6)) // If current mode is stretched,
+ {
+ If(And(Local1, 8)) // and if aspect ratio is enabled,
+ {
+ Store(8, PFIT) // request aspect ratio.
+ }
+ Else // Otherwise,
+ {
+ If(And(Local1, 1)) // if centered is enabled,
+ {
+ Store(1, PFIT) // request centered.
+ }
+ Else // Only stretched mode is enabled
+ {
+ Store(6, PFIT) // so request stretched. (No change.)
+ }
+ }
+ }
+ If(LEqual(Local0, 8)) // If current mode is aspect ratio,
+ {
+ If(And(Local1, 1)) // and if centered is enabled,
+ {
+ Store(1, PFIT) // request centered.
+ }
+ Else // Otherwise,
+ {
+ If(And(Local1, 6)) // if stretched is enabled,
+ {
+ Store(6, PFIT) // request stretched.
+ }
+ Else // Only aspect ratio mode is enabled
+ {
+ Store(8, PFIT) // so request aspect ratio. (No change.)
+ }
+ }
+ }
+ }
+ //
+ // The following code for panel fitting (within the Else condition) is retained for backward compatiblity.
+ //
+ Else // If CFPM field is zero use PFIT and toggle the
+ {
+ Xor(PFIT,7,PFIT) // mode setting between stretched and centered only.
+ }
+ Or(PFIT,0x80000000,PFIT) // Set the valid bit for all cases.
+ Store(4, ASLC) // Store "Panel fitting event" to ASLC[31:1]
+ }
+ Else
+ {
+ If(LEqual(Arg0, 1)) // Arg0=1, so set the backlight brightness.
+ {
+ Store(Divide(Multiply(Arg1, 255), 100), BCLP) // Convert from percent to 0-255.
+ Or(BCLP, 0x80000000, BCLP) // Set the valid bit.
+ Store(2, ASLC) // Store "Backlight control event" to ASLC[31:1]
+ }
+ Else
+ {
+ If(LEqual(Arg0, 0)) // Arg0=0, so set the ALS illuminace
+ {
+ Store(Arg1, ALSI)
+ Store(1, ASLC) // Store "ALS event" to ASLC[31:1]
+ }
+ Else
+ {
+ Return(0x1) // Unsupported function
+ }
+ }
+ }
+
+ Store(0x01, ASLE) // Generate ASLE interrupt
+ Return(0x0) // Return success
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxDsm.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxDsm.asl
new file mode 100644
index 0000000000..974f7b706d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxDsm.asl
@@ -0,0 +1,359 @@
+/** @file
+ IGD OpRegion/_DSM Reference Code.
+ This file contains Get BIOS Data and Callback functions for
+ the Integrated Graphics Device (IGD) OpRegion/DSM mechanism
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// _DSM Device Specific Method
+//
+// Arg0: UUID Unique function identifier
+// Arg1: Integer Revision Level
+// Arg2: Integer Function Index (1 = Return Supported Functions)
+// Arg3: Additional Inputs/Package Parameters Bits [31:0] input as {Byte0, Byte1, Byte2, Byte3} to BIOS which is passed as 32 bit DWORD by Driver
+//
+Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+
+ If (LEqual(Arg0, ToUUID ("3E5B41C6-EB1D-4260-9D15-C71FBADAE414"))) {
+ //
+ // _DSM Definition for Igd functions
+ // Arguments:
+ // Arg0: UUID: 3E5B41C6-EB1D-4260-9D15-C71FBADAE414
+ // Arg1: Revision ID: 1
+ // Arg2: Function Index: 16
+ // Arg3: Additional Inputs Bits[31:0] Arg3 {Byte0, Byte1, Byte2, Byte3}
+ //
+ // Return:
+ // Success for simple notification, Opregion update for some routines and a Package for AKSV
+ //
+ //
+ // Switch by function index
+ //
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index: 0
+ // Standard query - A bitmask of functions supported
+ //
+ // Return: A bitmask of functions supported
+ //
+ Case (0)
+ {
+ If (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+ Store("iGfx Supported Functions Bitmap ", Debug)
+ Return (0x1E7FF) // For SKL bit 11 and 12 is not supported
+ }
+ }
+
+ //
+ // Function Index: 1
+ // Adapter Power State Notification
+ // Arg3 Bits [7:0]: Adapter Power State bits [7:0] from Driver 00h = D0; 01h = D1; 02h = D2; 04h = D3 (Cold/Hot); 08h = D4 (Hibernate Notification)
+ // Return: Success
+ //
+ Case(1) {
+ If (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+ Store(" Adapter Power State Notification ", Debug)
+
+ //
+ // Handle Low Power S0 Idle Capability if enabled
+ //
+ If(LAnd(LEqual(S0ID, 1),LLess(OSYS, 2015))) {
+ //
+ // Call GUAM to trigger CS Entry
+ // If Adapter Power State Notification = D1 (Arg3[0]=0x01)
+ //
+ If (LEqual (And(DerefOf (Index (Arg3,0)), 0xFF), 0x01)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(One) // 0x01 - Power State Standby (CS Entry)
+ }
+ Store(And(DerefOf (Index (Arg3,1)), 0xFF), Local0)
+ //
+ // Call GUAM
+ // If Display Turn ON Notification (Arg3 [1] == 0) for CS Exit
+ //
+ If (LEqual (Local0, 0)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(0)
+ }
+ }
+
+ // Upon notification from driver that the Adapter Power State = D0,
+ // check if previous lid event failed. If it did, retry the lid
+ // event here.
+ If(LEqual(DerefOf (Index (Arg3,0)), 0)) {
+ Store(CLID, Local0)
+ If(And(0x80000000,Local0)) {
+ And(CLID, 0x0000000F, CLID)
+ GLID(CLID)
+ }
+ }
+ Return(0x01)
+ }
+ }
+ //
+ // Function Index: 2
+ // Display Power State Notification
+ // Arg3: Display Power State Bits [15:8]
+ // 00h = On
+ // 01h = Standby
+ // 02h = Suspend
+ // 04h = Off
+ // 08h = Reduced On
+ // Return: Success
+ //
+ Case(2) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+
+ Store("Display Power State Notification ", Debug)
+ Return(0x01)
+ }
+ }
+
+ //
+ // Function Index: 3
+ // BIOS POST Completion Notification
+ // Return: Success
+ //
+ Case(3) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+ Store("BIOS POST Completion Notification ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 4
+ // Pre-Hires Set Mode
+ // Return: Success
+ //
+ Case(4) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("Pre-Hires Set Mode ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 5
+ // Post-Hires Set Mode
+ // Return: Success
+ //
+ Case(5) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("Post-Hires Set Mode ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 6
+ // SetDisplayDeviceNotification (Display Switch)
+ // Return: Success
+ //
+ Case(6) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("SetDisplayDeviceNotification", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 7
+ // SetBootDevicePreference
+ // Return: Success
+ //
+ Case(7) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ //<TODO> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+
+ Store("SetBootDevicePreference ", Debug)
+ And(DerefOf (Index (Arg3,0)), 0xFF, IBTT) // Save the boot display to NVS
+ Return(0x01)
+ }
+ }
+
+ //
+ // Function Index: 8
+ // SetPanelPreference
+ // Return: Success
+ //
+ Case(8) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ // An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+
+ Store("SetPanelPreference ", Debug)
+
+ // Set the panel-related NVRAM variables based the input from the driver.
+ And(DerefOf (Index (Arg3,0)), 0xFF, IPSC)
+
+ // Change panel type if a change is requested by the driver (Change if
+ // panel type input is non-zero). Zero=No change requested.
+ If(And(DerefOf (Index (Arg3,1)), 0xFF)) {
+ And(DerefOf (Index (Arg3,1)), 0xFF, IPAT)
+ Decrement(IPAT) // 0 = no change, so fit to CMOS map
+ }
+ And(ShiftRight(DerefOf (Index (Arg3,2)), 4), 0x7, IBIA)
+ Return(0x01) // Success
+ }
+ }
+
+ //
+ // Function Index: 9
+ // FullScreenDOS
+ // Return: Success
+ //
+ Case(9) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("FullScreenDOS ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 10
+ // APM Complete
+ // Return: Adjusted Lid State
+ //
+ Case(10) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+
+ Store("APM Complete ", Debug)
+ Store(ShiftLeft(LIDS, 8), Local0) // Report the lid state
+ Add(Local0, 0x100, Local0) // Adjust the lid state, 0 = Unknown
+ Return(Local0)
+ }
+ }
+
+ //
+ //
+ // Function Index: 13
+ // GetBootDisplayPreference
+ // Arg3 Bits [30:16] : Boot Device Ports
+ // Arg3 Bits [7:0] : Boot Device Type
+ // Return: Boot device port and Boot device type from saved configuration
+ //
+ Case(13) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+
+ Store("GetBootDisplayPreference ", Debug)
+ Or(ShiftLeft(DerefOf (Index (Arg3,3)), 24), ShiftLeft(DerefOf (Index (Arg3,2)), 16), Local0) // Combine Arg3 Bits [31:16]
+ And(Local0, 0xEFFF0000, Local0)
+ And(Local0, ShiftLeft(DeRefOf(Index(DBTB, IBTT)), 16), Local0)
+ Or(IBTT, Local0, Local0) // Arg3 Bits [7:0] = Boot device type
+ Return(Local0)
+ }
+ }
+
+ //
+ // Function Index: 14
+ // GetPanelDetails
+ // Return: Different Panel Settings
+ //
+ Case(14) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("GetPanelDetails ", Debug)
+
+ // Report the scaling setting
+ // Bits [7:0] - Panel Scaling
+ // Bits contain the panel scaling user setting from CMOS
+ // 00h = On: Auto
+ // 01h = On: Force Scaling
+ // 02h = Off
+ // 03h = Maintain Aspect Ratio
+
+ Store(IPSC, Local0)
+ Or(Local0, ShiftLeft(IPAT, 8), Local0)
+
+ // Adjust panel type, 0 = VBT default
+ // Bits [15:8] - Panel Type
+ // Bits contain the panel type user setting from CMOS
+ // 00h = Not Valid, use default Panel Type & Timings from VBT
+ // 01h - 0Fh = Panel Number
+
+ Add(Local0, 0x100, Local0)
+
+ // Report the lid state and Adjust it
+ // Bits [16] - Lid State
+ // Bits contain the current panel lid state
+ // 0 = Lid Open
+ // 1 = Lid Closed
+
+ Or(Local0, ShiftLeft(LIDS, 16), Local0)
+ Add(Local0, 0x10000, Local0)
+
+ // Report the BIA setting
+ // Bits [22:20] - Backlight Image Adaptation (BIA) Control
+ // Bits contain the backlight image adaptation control user setting from CMOS
+ // 000 = VBT Default
+ // 001 = BIA Disabled (BLC may still be enabled)
+ // 010 - 110 = BIA Enabled at Aggressiveness Level [1 - 5]
+
+ Or(Local0, ShiftLeft(IBIA, 20), Local0)
+ Return(Local0)
+ }
+ }
+
+ //
+ // Function Index: 15
+ // GetInternalGraphics
+ // Return: Different Internal Grahics Settings
+ //
+
+ Case(15) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("GetInternalGraphics ", Debug)
+
+ Store(GIVD, Local0) // Local0[0] - VGA mode(1=VGA)
+ Xor(Local0, 1, Local0) // Invert the VGA mode polarity
+ Or(Local0, ShiftLeft(3, 11), Local0) // Local0[12:11] - DVMT version (11b = 5.0)
+
+ //
+ // Report DVMT 5.0 Total Graphics memory size.
+ //
+ Or(Local0, ShiftLeft(IDMS, 17), Local0) // Bits 20:17 are for Gfx total memory size
+ Return(Local0)
+ }
+ }
+
+ //
+ // Function Index: 16
+ // GetAKSV
+ // Retrun: 5 bytes of AKSV
+ //
+ Case(16) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+
+ Store("GetAKSV ", Debug)
+ Name (KSVP, Package()
+ {
+ 0x80000000,
+ 0x8000
+ })
+ Store(KSV0, Index(KSVP,0)) // First four bytes of AKSV
+ Store(KSV1, Index(KSVP,1)) // Fifth byte of AKSV
+ Return(KSVP) // Success
+ }
+ }
+ } // End of switch(Arg2)
+
+ } // End of if (ToUUID("3E5B41C6-EB1D-4260-9D15-C71FBADAE414D"))
+
+
+ Return (Buffer () {0x00})
+} // End of _DSM
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpGbda.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpGbda.asl
new file mode 100644
index 0000000000..cd86e25fca
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpGbda.asl
@@ -0,0 +1,119 @@
+/** @file
+ IGD OpRegion/Software SCI Reference Code.
+ This file contains Get BIOS Data Area funciton support for
+ the Integrated Graphics Device (IGD) OpRegion/Software SCI mechanism
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+Method (GBDA, 0, Serialized)
+{
+ //
+ // Supported calls: Sub-function 0
+ //
+ If (LEqual(GESF, 0))
+ {
+ //
+ //<NOTE> Reference code is set to Intel's validated implementation.
+ //
+ Store(0x0000659, PARM)
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Success
+ }
+ //
+ // Requested callbacks: Sub-function 1
+ //
+ If (LEqual(GESF, 1))
+ {
+ //
+ //<NOTE> Call back functions are where the driver calls the
+ // system BIOS at function indicated event.
+ //
+ Store(0x300482, PARM)
+ If(LEqual(S0ID, One)){
+ Or(PARM, 0x100, PARM) //Request Fn 8 callback in CS systems
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Success
+ }
+ //
+ // Get Boot display Preferences: Sub-function 4
+ //
+ If (LEqual(GESF, 4))
+ {
+ //
+ //<NOTE> Get Boot Display Preferences function.
+ //
+ And(PARM, 0xEFFF0000, PARM) // PARM[30:16] = Boot device ports
+ And(PARM, ShiftLeft(DeRefOf(Index(DBTB, IBTT)), 16), PARM)
+ Or(IBTT, PARM, PARM) // PARM[7:0] = Boot device type
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Success
+ }
+ //
+ // Panel details: Sub-function 5
+ //
+ If (LEqual(GESF, 5))
+ {
+ //
+ //<NOTE> Get Panel Details function.
+ //
+ Store(IPSC, PARM) // Report the scaling setting
+ Or(PARM, ShiftLeft(IPAT, 8), PARM)
+ Add(PARM, 0x100, PARM) // Adjust panel type, 0 = VBT default
+ Or(PARM, ShiftLeft(LIDS, 16), PARM) // Report the lid state
+ Add(PARM, 0x10000, PARM) // Adjust the lid state, 0 = Unknown
+ Or(PARM, ShiftLeft(IBIA, 20), PARM) // Report the BIA setting
+ Store(Zero, GESF)
+ Return(SUCC)
+ }
+ //
+ // Internal graphics: Sub-function 7
+ //
+ If (LEqual(GESF, 7))
+ {
+ Store(GIVD, PARM) // PARM[0] - VGA mode(1=VGA)
+ Xor(PARM, 1, PARM) // Invert the VGA mode polarity
+ Or(PARM, ShiftLeft(3, 11), PARM) // PARM[12:11] - DVMT mode(11b = 5.0)
+
+ //
+ // Report DVMT 5.0 Total Graphics memory size.
+ //
+ Or(PARM, ShiftLeft(IDMS, 17), PARM) // Bits 20:17 are for Gfx total memory size
+ Store(1, GESF) // Set the modified settings flag
+ Return(SUCC)
+ }
+ //
+ // Spread spectrum clocks: Sub-function 10
+ //
+ If (LEqual(GESF, 10))
+ {
+ Store(0, PARM) // Assume SSC is disabled
+ If(ISSC)
+ {
+ Or(PARM, 3, PARM) // If SSC enabled, return SSC1+Enabled
+ }
+ Store(0, GESF) // Set the modified settings flag
+ Return(SUCC) // Success
+ }
+
+ If (LEqual(GESF, 11))
+ {
+ Store(KSV0, PARM) // First four bytes of AKSV
+ Store(KSV1, GESF) // Fifth byte of AKSV
+
+ Return(SUCC) // Success
+ }
+ //
+ // A call to a reserved "Get BIOS data" function was received.
+ //
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(CRIT) // Reserved, "Critical failure"
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpRn.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpRn.asl
new file mode 100644
index 0000000000..4e3b6c5522
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpRn.asl
@@ -0,0 +1,297 @@
+/** @file
+ IGD OpRegion/Software SCI Reference Code.
+ This file contains the interrupt handler code for the Integrated
+ Graphics Device (IGD) OpRegion/Software SCI mechanism.
+ It defines OperationRegions to cover the IGD PCI configuration space
+ as described in the IGD OpRegion specification.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+//
+//NOTES:
+//
+// (1) The code contained in this file inherits the scope in which it
+// was included. So BIOS developers must be sure to include this
+// file in the scope associated with the graphics device
+// (ex. \_SB.PCI0.GFX0).
+// (2) Create a _L06 method under the GPE scope to handle the event
+// generated by the graphics driver. The _L06 method must call
+// the GSCI method in this file.
+// (3) The MCHP operation region assumes that _ADR and _BBN names
+// corresponding to bus 0, device0, function 0 have been declared
+// under the PCI0 scope.
+// (4) Before the first execution of the GSCI method, the base address
+// of the GMCH SCI OpRegion must be programmed where the driver can
+// access it. A 32bit scratch register at 0xFC in the IGD PCI
+// configuration space (B0/D2/F0/R0FCh) is used for this purpose.
+
+// Define an OperationRegion to cover the GMCH PCI configuration space as
+// described in the IGD OpRegion specificiation.
+//
+
+//
+// Define an OperationRegion to cover the IGD PCI configuration space as
+// described in the IGD OpRegion specificiation.
+//
+OperationRegion(IGDP, PCI_Config, 0x40, 0xC0)
+Field(IGDP, AnyAcc, NoLock, Preserve)
+{
+ Offset(0x10), // Mirror of gfx control reg
+ , 1,
+ GIVD, 1, // IGD VGA disable bit
+ , 2,
+ GUMA, 3, // Stolen memory size
+ , 9,
+ Offset(0xA4),
+ ASLE, 8, // Reg 0xE4, ASLE interrupt register
+ , 24, // Only use first byte of ASLE reg
+ Offset(0xA8), // Reg 0xE8, SWSCI control register
+ GSSE, 1, // Graphics SCI event (1=event pending)
+ GSSB, 14, // Graphics SCI scratchpad bits
+ GSES, 1, // Graphics event select (1=SCI)
+ Offset(0xBC),
+ ASLS, 32, // Reg 0xFC, Address of the IGD OpRegion
+
+}
+
+//
+// Define an OperationRegion to cover the IGD OpRegion layout.
+//
+OperationRegion(IGDM, SystemMemory, ASLB, 0x2000)
+Field(IGDM, AnyAcc, NoLock, Preserve)
+{
+ //
+ // OpRegion Header
+ //
+ SIGN, 128, // Signature-"IntelGraphicsMem"
+ SIZE, 32, // OpRegion Size
+ OVER, 32, // OpRegion Version
+ SVER, 256, // System BIOS Version
+ VVER, 128, // VBIOS Version
+ GVER, 128, // Driver version
+ MBOX, 32, // Mailboxes supported
+ DMOD, 32, // Driver Model
+ PCON, 32, // Platform Configuration
+ DVER, 64, // GOP Version
+ //
+ // OpRegion Mailbox 1 (Public ACPI Methods)
+ // Note: Mailbox 1 is normally reserved for desktop platforms.
+ //
+ Offset(0x100),
+ DRDY, 32, // Driver readiness (ACPI notification)
+ CSTS, 32, // Notification status
+ CEVT, 32, // Current event
+ Offset(0x120),
+ DIDL, 32, // Supported display device ID list
+ DDL2, 32, // Allows for 8 devices
+ DDL3, 32,
+ DDL4, 32,
+ DDL5, 32,
+ DDL6, 32,
+ DDL7, 32,
+ DDL8, 32,
+ CPDL, 32, // Currently present display list
+ CPL2, 32, // Allows for 8 devices
+ CPL3, 32,
+ CPL4, 32,
+ CPL5, 32,
+ CPL6, 32,
+ CPL7, 32,
+ CPL8, 32,
+ CADL, 32, // Currently active display list
+ CAL2, 32, // Allows for 8 devices
+ CAL3, 32,
+ CAL4, 32,
+ CAL5, 32,
+ CAL6, 32,
+ CAL7, 32,
+ CAL8, 32,
+ NADL, 32, // Next active display list
+ NDL2, 32, // Allows for 8 devices
+ NDL3, 32,
+ NDL4, 32,
+ NDL5, 32,
+ NDL6, 32,
+ NDL7, 32,
+ NDL8, 32,
+ ASLP, 32, // ASL sleep timeout
+ TIDX, 32, // Toggle table index
+ CHPD, 32, // Current hot plug enable indicator
+ CLID, 32, // Current lid state indicator
+ CDCK, 32, // Current docking state indicator
+ SXSW, 32, // Display switch notify on resume
+ EVTS, 32, // Events supported by ASL (diag only)
+ CNOT, 32, // Current OS notifications (diag only)
+ NRDY, 32,
+ //
+ //Extended DIDL list
+ //
+ DDL9, 32,
+ DD10, 32,
+ DD11, 32,
+ DD12, 32,
+ DD13, 32,
+ DD14, 32,
+ DD15, 32,
+ //
+ //Extended Currently attached Display Device List CPD2
+ //
+ CPL9, 32,
+ CP10, 32,
+ CP11, 32,
+ CP12, 32,
+ CP13, 32,
+ CP14, 32,
+ CP15, 32,
+ //
+ // OpRegion Mailbox 2 (Software SCI Interface)
+ //
+ Offset(0x200), // SCIC
+ SCIE, 1, // SCI entry bit (1=call unserviced)
+ GEFC, 4, // Entry function code
+ GXFC, 3, // Exit result
+ GESF, 8, // Entry/exit sub-function/parameter
+ , 16, // SCIC[31:16] reserved
+ Offset(0x204), // PARM
+ PARM, 32, // PARM register (extra parameters)
+ DSLP, 32, // Driver sleep time out
+ //
+ // OpRegion Mailbox 3 (BIOS to Driver Notification)
+ // Note: Mailbox 3 is normally reserved for desktop platforms.
+ //
+ Offset(0x300),
+ ARDY, 32, // Driver readiness (power conservation)
+ ASLC, 32, // ASLE interrupt command/status
+ TCHE, 32, // Technology enabled indicator
+ ALSI, 32, // Current ALS illuminance reading
+ BCLP, 32, // Backlight brightness
+ PFIT, 32, // Panel fitting state or request
+ CBLV, 32, // Current brightness level
+ BCLM, 320, // Backlight brightness level duty cycle mapping table
+ CPFM, 32, // Current panel fitting mode
+ EPFM, 32, // Enabled panel fitting modes
+ PLUT, 592, // Optional. 74-byte Panel LUT Table
+ PFMB, 32, // Optional. PWM Frequency and Minimum Brightness
+ CCDV, 32, // Optional. Gamma, Brightness, Contrast values.
+ PCFT, 32, // Optional. Power Conservation Features
+ SROT, 32, // Supported rotation angle.
+ IUER, 32, // Optional. Intel Ultrabook Event Register.
+ FDSP, 64, // Optional. FFS Display Physical address
+ FDSS, 32, // Optional. FFS Display Size
+ STAT, 32, // State Indicator
+ //
+ // OpRegion Mailbox 4 (VBT)
+ //
+ Offset(0x400),
+ GVD1, 0xC000, // 6K bytes maximum VBT image
+ //
+ // OpRegion Mailbox 5 (BIOS to Driver Notification Extension)
+ //
+ Offset(0x1C00),
+ PHED, 32, // Panel Header
+ BDDC, 2048, // Panel EDID (Max 256 bytes)
+
+}
+
+//
+// Convert boot display type into a port mask.
+//
+Name (DBTB, Package()
+{
+ 0x0000, // Automatic
+ 0x0007, // Port-0 : Integrated CRT
+ 0x0038, // Port-1 : DVO-A, or Integrated LVDS
+ 0x01C0, // Port-2 : SDVO-B, or SDVO-B/C
+ 0x0E00, // Port-3 : SDVO-C
+ 0x003F, // [CRT + DVO-A / Integrated LVDS]
+ 0x01C7, // [CRT + SDVO-B] or [CRT + SDVO-B/C]
+ 0x0E07, // [CRT + SDVO-C]
+ 0x01F8, // [DVO-A / Integrated LVDS + SDVO-B]
+ 0x0E38, // [DVO-A / Integrated LVDS + SDVO-C]
+ 0x0FC0, // [SDVO-B + SDVO-C]
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x7000, // Port-4: Integrated TV
+ 0x7007, // [Integrated TV + CRT]
+ 0x7038, // [Integrated TV + LVDS]
+ 0x71C0, // [Integrated TV + DVOB]
+ 0x7E00 // [Integrated TV + DVOC]
+})
+
+//
+// Core display clock value table.
+//
+Name (CDCT, Package()
+{
+ Package() {228, 320},
+ Package() {222, 333},
+ Package() {222, 333},
+ Package() { 0, 0},
+ Package() {222, 333},
+})
+
+//
+// Defined exit result values:
+//
+Name (SUCC, 1) // Exit result: Success
+Name (NVLD, 2) // Exit result: Invalid parameter
+Name (CRIT, 4) // Exit result: Critical failure
+Name (NCRT, 6) // Exit result: Non-critical failure
+
+/************************************************************************;
+;*
+;* Name: GSCI
+;*
+;* Description: Handles an SCI generated by the graphics driver. The
+;* PARM and SCIC input fields are parsed to determine the
+;* functionality requested by the driver. GBDA or SBCB
+;* is called based on the input data in SCIC.
+;*
+;* Usage: The method must be called in response to a GPE 06 event
+;* which will be generated by the graphics driver.
+;* Ex: Method(\_GPE._L06) {Return(\_SB.PCI0.GFX0.GSCI())}
+;*
+;* Input: PARM and SCIC are indirect inputs
+;*
+;* Output: PARM and SIC are indirect outputs
+;*
+;* References: GBDA (Get BIOS Data method), SBCB (System BIOS Callback
+;* method)
+;*
+;************************************************************************/
+
+Method (GSCI, 0, Serialized)
+{
+ Include("IgfxOpGbda.asl") // "Get BIOS Data" Functions
+ Include("IgfxOpSbcb.asl") // "System BIOS CallBacks"
+
+ If (LEqual(GEFC, 4))
+ {
+ Store(GBDA(), GXFC) // Process Get BIOS Data functions
+ }
+
+ If (LEqual(GEFC, 6))
+ {
+ Store(SBCB(), GXFC) // Process BIOS Callback functions
+ }
+
+ Store(0, GEFC) // Wipe out the entry function code
+ Store(1, CPSC) // Clear CPUSCI_STS to clear the PCH TCO SCI status
+ Store(0, GSSE) // Clear the SCI generation bit in PCI space.
+ Store(0, SCIE) // Clr SCI serviced bit to signal completion
+
+ Return(Zero)
+}
+
+Include("IgfxCommon.asl") // IGD SCI mobile features
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpSbcb.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpSbcb.asl
new file mode 100644
index 0000000000..1f688e3b4a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/IgfxOpSbcb.asl
@@ -0,0 +1,268 @@
+/** @file
+ This file contains the system BIOS call back functionality for the
+ OpRegion/Software SCI mechanism.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+Method (SBCB, 0, Serialized)
+{
+ //
+ // Supported Callbacks: Sub-function 0
+ //
+ If (LEqual(GESF, 0x0))
+ {
+ //
+ //<NOTE> An OEM may support the driver->SBIOS status callbacks, but
+ // the supported callbacks value must be modified. The code that is
+ // executed upon reception of the callbacks must be also be updated
+ // to perform the desired functionality.
+ //
+ Store(0x00000000, PARM) // No callbacks supported
+ //Store(0x000787FD, PARM) // Used for Intel test implementaion
+ Store(0x000F87DD, PARM)
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // "Success"
+ }
+ //
+ // BIOS POST Completion: Sub-function 1
+ //
+ If (LEqual(GESF, 1))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Pre-Hires Set Mode: Sub-function 3
+ //
+ If (LEqual(GESF, 3))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Post-Hires Set Mode: Sub-function 4
+ //
+ If (LEqual(GESF, 4))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Display Switch: Sub-function 5
+ //
+ If (LEqual(GESF, 5))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Adapter Power State: Sub-function 7
+ //
+ If (LEqual(GESF, 7))
+ {
+ //
+ // Handle Low Power S0 Idle Capability if enabled
+ //
+ If(LAnd(LEqual(S0ID, 1),LLess(OSYS, 2015))) {
+ //
+ // Call GUAM to trigger CS Entry
+ // If Adapter Power State Notification = D1 (PARM[7:0]=0x01)
+ //
+ If (LEqual (And(PARM,0xFF), 0x01)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(One) // 0x01 - Power State Standby (CS Entry)
+ }
+ If (LEqual (And(PARM,0xFF), 0x00)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(0)
+ }
+ }
+ //
+ // Upon notification from driver that the Adapter Power State = D0,
+ // check if previous lid event failed. If it did, retry the lid
+ // event here.
+ //
+ If(LEqual(PARM, 0))
+ {
+ Store(CLID, Local0)
+ If(And(0x80000000,Local0))
+ {
+ And(CLID, 0x0000000F, CLID)
+ GLID(CLID)
+ }
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Display Power State: Sub-function 8
+ //
+ If (LEqual(GESF, 8))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Set Boot Display: Sub-function 9
+ //
+ If (LEqual(GESF, 9))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ //
+ And(PARM, 0xFF, IBTT) // Save the boot display to NVS
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Reserved, "Critical failure"
+ }
+ //
+ // Set Panel Details: Sub-function 10 (0Ah)
+ //
+ If (LEqual(GESF, 10))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ // Set the panel-related NVRAM variables based the input from the driver.
+ //
+ And(PARM, 0xFF, IPSC)
+ //
+ // Change panel type if a change is requested by the driver (Change if
+ // panel type input is non-zero). Zero=No change requested.
+ //
+ If(And(ShiftRight(PARM, 8), 0xFF))
+ {
+ And(ShiftRight(PARM, 8), 0xFF, IPAT)
+ Decrement(IPAT) // 0 = no change, so fit to CMOS map
+ }
+ And(ShiftRight(PARM, 20), 0x7, IBIA)
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+ //
+ // Set Internal Graphics: Sub-function 11 (0Bh)
+ //
+ If (LEqual(GESF, 11))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ //
+ And(ShiftRight(PARM, 1), 1, IF1E) // Program the function 1 option
+ If(And(PARM, ShiftLeft(0xF, 13))) // Use fixed memory if fixed size != 0
+ {
+ //
+ // Fixed memory
+ //
+ And(ShiftRight(PARM, 13), 0xF, IDMS) // Program fixed memory size
+ }
+ Else
+ {
+ //
+ // DVMT memory
+ //
+ And(ShiftRight(PARM, 17), 0xF, IDMS) // Program fixed memory size
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+ //
+ // Post-Hires to DOS FS: Sub-function 16 (10h)
+ //
+ If (LEqual(GESF, 16))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // APM Complete: Sub-function 17 (11h)
+ //
+ If (LEqual(GESF, 17))
+ {
+ Store(ShiftLeft(LIDS, 8), PARM) // Report the lid state
+ Add(PARM, 0x100, PARM) // Adjust the lid state, 0 = Unknown
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Set Spread Spectrum Clocks: Sub-function 18 (12h)
+ //
+ If (LEqual(GESF, 18))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ //
+ If(And(PARM, 1))
+ {
+ If(LEqual(ShiftRight(PARM, 1), 1))
+ {
+ Store(1, ISSC) // Enable HW SSC, only for clock 1
+ }
+ Else
+ {
+ Store(Zero, GESF)
+ Return(CRIT) // Failure, as the SSC clock must be 1
+ }
+ }
+ Else
+ {
+ Store(0, ISSC) // Disable SSC
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+ //
+ // Post VBE/PM Callback: Sub-function 19 (13h)
+ //
+ If (LEqual(GESF, 19))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Set PAVP Data: Sub-function 20 (14h)
+ //
+ If (LEqual(GESF, 20))
+ {
+ And(PARM, 0xF, PAVP) // Store PAVP info
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+
+ //
+ // A call to a reserved "System BIOS callbacks" function was received
+ //
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Reserved, "Critical failure"
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl
new file mode 100644
index 0000000000..7bc2d80667
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl
@@ -0,0 +1,32 @@
+/** @file
+ This file contains the device definition of the System Agent
+ ACPI reference code.
+ Currently defines the device objects for the
+ System Agent PCI Express* ports (PEG), iGfx and other devices.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+External(\_SB.PCI0, DeviceObj)
+External(\_SB.PCI0.GFX0, DeviceObj)
+External(\_SB.PCI0.PCIC, MethodObj)
+External(\_SB.PCI0.PCID, MethodObj)
+
+
+///
+/// I.G.D
+///
+Scope (\_SB.PCI0.GFX0)
+{
+ include("Igfx.asl")
+} // end I.G.D
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl
new file mode 100644
index 0000000000..311810020f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl
@@ -0,0 +1,135 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+ //
+ // Define SA NVS Area operatino region.
+ //
+
+
+
+ OperationRegion(SANV,SystemMemory, 0xFFFF0000,0xAA55)
+ Field(SANV,AnyAcc,Lock,Preserve)
+ {
+ Offset(0), ASLB, 32, // Offset(0), IGD OpRegion base address
+ Offset(4), IMON, 8, // Offset(4), IMON Current Value
+ Offset(5), IGDS, 8, // Offset(5), IGD State (Primary Display = 1)
+ Offset(6), IBTT, 8, // Offset(6), IGD Boot Display Device
+ Offset(7), IPAT, 8, // Offset(7), IGD Panel Type CMOS option
+ Offset(8), IPSC, 8, // Offset(8), IGD Panel Scaling
+ Offset(9), IBIA, 8, // Offset(9), IGD BIA Configuration
+ Offset(10), ISSC, 8, // Offset(10), IGD SSC Configuration
+ Offset(11), IDMS, 8, // Offset(11), IGD DVMT Memory Size
+ Offset(12), IF1E, 8, // Offset(12), IGD Function 1 Enable
+ Offset(13), HVCO, 8, // Offset(13), HPLL VCO
+ Offset(14), GSMI, 8, // Offset(14), GMCH SMI/SCI mode (0=SCI)
+ Offset(15), PAVP, 8, // Offset(15), IGD PAVP data
+ Offset(16), CADL, 8, // Offset(16), Current Attached Device List
+ Offset(17), CSTE, 16, // Offset(17), Current Display State
+ Offset(19), NSTE, 16, // Offset(19), Next Display State
+ Offset(21), NDID, 8, // Offset(21), Number of Valid Device IDs
+ Offset(22), DID1, 32, // Offset(22), Device ID 1
+ Offset(26), DID2, 32, // Offset(26), Device ID 2
+ Offset(30), DID3, 32, // Offset(30), Device ID 3
+ Offset(34), DID4, 32, // Offset(34), Device ID 4
+ Offset(38), DID5, 32, // Offset(38), Device ID 5
+ Offset(42), DID6, 32, // Offset(42), Device ID 6
+ Offset(46), DID7, 32, // Offset(46), Device ID 7
+ Offset(50), DID8, 32, // Offset(50), Device ID 8
+ Offset(54), DID9, 32, // Offset(54), Device ID 9
+ Offset(58), DIDA, 32, // Offset(58), Device ID 10
+ Offset(62), DIDB, 32, // Offset(62), Device ID 11
+ Offset(66), DIDC, 32, // Offset(66), Device ID 12
+ Offset(70), DIDD, 32, // Offset(70), Device ID 13
+ Offset(74), DIDE, 32, // Offset(74), Device ID 14
+ Offset(78), DIDF, 32, // Offset(78), Device ID 15
+ Offset(82), DIDX, 32, // Offset(82), Device ID for eDP device
+ Offset(86), NXD1, 32, // Offset(86), Next state DID1 for _DGS
+ Offset(90), NXD2, 32, // Offset(90), Next state DID2 for _DGS
+ Offset(94), NXD3, 32, // Offset(94), Next state DID3 for _DGS
+ Offset(98), NXD4, 32, // Offset(98), Next state DID4 for _DGS
+ Offset(102), NXD5, 32, // Offset(102), Next state DID5 for _DGS
+ Offset(106), NXD6, 32, // Offset(106), Next state DID6 for _DGS
+ Offset(110), NXD7, 32, // Offset(110), Next state DID7 for _DGS
+ Offset(114), NXD8, 32, // Offset(114), Next state DID8 for _DGS
+ Offset(118), NXDX, 32, // Offset(118), Next state DID for eDP
+ Offset(122), LIDS, 8, // Offset(122), Lid State (Lid Open = 1)
+ Offset(123), KSV0, 32, // Offset(123), First four bytes of AKSV (manufacturing mode)
+ Offset(127), KSV1, 8, // Offset(127), Fifth byte of AKSV (manufacturing mode)
+ Offset(128), BRTL, 8, // Offset(128), Brightness Level Percentage
+ Offset(129), ALSE, 8, // Offset(129), Ambient Light Sensor Enable
+ Offset(130), ALAF, 8, // Offset(130), Ambient Light Adjusment Factor
+ Offset(131), LLOW, 8, // Offset(131), LUX Low Value
+ Offset(132), LHIH, 8, // Offset(132), LUX High Value
+ Offset(133), ALFP, 8, // Offset(133), Active LFP
+ Offset(134), IMTP, 8, // Offset(134), IMGU ACPI device type
+ Offset(135), EDPV, 8, // Offset(135), Check for eDP display device
+ Offset(136), SGMD, 8, // Offset(136), SG Mode (0=Disabled, 1=SG Muxed, 2=SG Muxless, 3=DGPU Only)
+ Offset(137), SGFL, 8, // Offset(137), SG Feature List
+ Offset(138), SGGP, 8, // Offset(138), PCIe0 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ Offset(139), HRE0, 8, // Offset(139), PCIe0 HLD RST IO Expander Number
+ Offset(140), HRG0, 32, // Offset(140), PCIe0 HLD RST GPIO Number
+ Offset(144), HRA0, 8, // Offset(144), PCIe0 HLD RST GPIO Active Information
+ Offset(145), PWE0, 8, // Offset(145), PCIe0 PWR Enable IO Expander Number
+ Offset(146), PWG0, 32, // Offset(146), PCIe0 PWR Enable GPIO Number
+ Offset(150), PWA0, 8, // Offset(150), PCIe0 PWR Enable GPIO Active Information
+ Offset(151), P1GP, 8, // Offset(151), PCIe1 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ Offset(152), HRE1, 8, // Offset(152), PCIe1 HLD RST IO Expander Number
+ Offset(153), HRG1, 32, // Offset(153), PCIe1 HLD RST GPIO Number
+ Offset(157), HRA1, 8, // Offset(157), PCIe1 HLD RST GPIO Active Information
+ Offset(158), PWE1, 8, // Offset(158), PCIe1 PWR Enable IO Expander Number
+ Offset(159), PWG1, 32, // Offset(159), PCIe1 PWR Enable GPIO Number
+ Offset(163), PWA1, 8, // Offset(163), PCIe1 PWR Enable GPIO Active Information
+ Offset(164), P2GP, 8, // Offset(164), PCIe2 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ Offset(165), HRE2, 8, // Offset(165), PCIe2 HLD RST IO Expander Number
+ Offset(166), HRG2, 32, // Offset(166), PCIe2 HLD RST GPIO Number
+ Offset(170), HRA2, 8, // Offset(170), PCIe2 HLD RST GPIO Active Information
+ Offset(171), PWE2, 8, // Offset(171), PCIe2 PWR Enable IO Expander Number
+ Offset(172), PWG2, 32, // Offset(172), PCIe2 PWR Enable GPIO Number
+ Offset(176), PWA2, 8, // Offset(176), PCIe2 PWR Enable GPIO Active Information
+ Offset(177), DLPW, 16, // Offset(177), Delay after power enable for PCIe
+ Offset(179), DLHR, 16, // Offset(179), Delay after Hold Reset for PCIe
+ Offset(181), EECP, 8, // Offset(181), PCIe0 Endpoint Capability Structure Offset
+ Offset(182), XBAS, 32, // Offset(182), Any Device's PCIe Config Space Base Address
+ Offset(186), GBAS, 16, // Offset(186), GPIO Base Address
+ Offset(188), NVGA, 32, // Offset(188), NVIG opregion address
+ Offset(192), NVHA, 32, // Offset(192), NVHM opregion address
+ Offset(196), AMDA, 32, // Offset(196), AMDA opregion address
+ Offset(200), LTRX, 8, // Offset(200), Latency Tolerance Reporting Enable
+ Offset(201), OBFX, 8, // Offset(201), Optimized Buffer Flush and Fill
+ Offset(202), LTRY, 8, // Offset(202), Latency Tolerance Reporting Enable
+ Offset(203), OBFY, 8, // Offset(203), Optimized Buffer Flush and Fill
+ Offset(204), LTRZ, 8, // Offset(204), Latency Tolerance Reporting Enable
+ Offset(205), OBFZ, 8, // Offset(205), Optimized Buffer Flush and Fill
+ Offset(206), SMSL, 16, // Offset(206), SA Peg Latency Tolerance Reporting Max Snoop Latency
+ Offset(208), SNSL, 16, // Offset(208), SA Peg Latency Tolerance Reporting Max No Snoop Latency
+ Offset(210), P0UB, 8, // Offset(210), Peg0 Unused Bundle Control
+ Offset(211), P1UB, 8, // Offset(211), Peg1 Unused Bundle Control
+ Offset(212), P2UB, 8, // Offset(212), Peg2 Unused Bundle Control
+ Offset(213), PCSL, 8, // Offset(213), The lowest C-state for the package
+ Offset(214), PBGE, 8, // Offset(214), Pegx Unused Bundle Control Global Enable (0=Disabled, 1=Enabled)
+ Offset(215), M64B, 64, // Offset(215), Base of above 4GB MMIO resource
+ Offset(223), M64L, 64, // Offset(223), Length of above 4GB MMIO resource
+ Offset(231), CPEX, 32, // Offset(231), CPU ID info to get Family Id or Stepping
+ Offset(235), EEC1, 8, // Offset(235), PCIe1 Endpoint Capability Structure Offset
+ Offset(236), EEC2, 8, // Offset(236), PCIe2 Endpoint Capability Structure Offset
+ Offset(237), SBN0, 8, // Offset(237), PCIe0 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ Offset(238), SBN1, 8, // Offset(238), PCIe1 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ Offset(239), SBN2, 8, // Offset(239), PCIe2 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ Offset(240), M32B, 32, // Offset(240), Base of below 4GB MMIO resource
+ Offset(244), M32L, 32, // Offset(244), Length of below 4GB MMIO resource
+ Offset(248), P0WK, 32, // Offset(248), PCIe0 RTD3 Device Wake GPIO Number
+ Offset(252), P1WK, 32, // Offset(252), PCIe1 RTD3 Device Wake GPIO Number
+ Offset(256), P2WK, 32, // Offset(256), PCIe2 RTD3 Device Wake GPIO Number
+ Offset (500), // Offset(260) : Offset(499), Reserved bytes
+ Offset (503), // Offset(500) : Offset(502), Reserved bytes
+ }
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl
new file mode 100644
index 0000000000..b19a3cfa7b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl
@@ -0,0 +1,28 @@
+/** @file
+ This file contains the SystemAgent SSDT Table ASL code.
+ It defines a Global NVS table which exchanges datas between OS
+ and BIOS.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+DefinitionBlock (
+ "SaSsdt.aml",
+ "SSDT",
+ 0x02,
+ "SaSsdt",
+ "SaSsdt ",
+ 0x3000
+ )
+{
+ include ("SaNvs.asl")
+ include ("Sa.asl")
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf
new file mode 100644
index 0000000000..43d7819263
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf
@@ -0,0 +1,60 @@
+## @file
+# Component description file for the ACPI tables
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+
+[Defines]
+INF_VERSION = 0x00010005
+BASE_NAME = SaSsdt
+FILE_GUID = ca89914d-2317-452e-b245-36c6fb77a9c6
+MODULE_TYPE = USER_DEFINED
+VERSION_STRING = 1.0
+
+[Sources]
+ SaSsdt.asl
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+[Pcd]
+
+[Protocols]
+
+[PPIs]
+
+[Guids]
+
+[Depex]
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsDxeConfig.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsDxeConfig.h
new file mode 100644
index 0000000000..8f746dcc95
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsDxeConfig.h
@@ -0,0 +1,57 @@
+/** @file
+ Graphics DXE Policy definitions
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GRAPHICS_DXE_CONFIG_H_
+#define _GRAPHICS_DXE_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#define GRAPHICS_DXE_CONFIG_REVISION 2
+
+/**
+ This configuration block is to configure IGD related variables used in DXE.
+ If Intel Gfx Device is not supported or disabled, all policies will be ignored.
+ The data elements should be initialized by a Platform Module.\n
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Deprecated IgdBiaConfig and IgdSscConfig.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27: Config Block Header
+ UINT32 Size; ///< Offset 28 - 31: This field gives the size of the GOP VBT Data buffer
+ EFI_PHYSICAL_ADDRESS VbtAddress; ///< Offset 32 - 39: This field points to the GOP VBT data buffer
+ UINT8 PlatformConfig; ///< Offset 40: This field gives the Platform Configuration Information (0=Platform is S0ix Capable for ULT SKUs only, <b>1=Platform is not S0ix Capable</b>, 2=Force Platform is S0ix Capable for All SKUs)
+ UINT8 AlsEnable; ///< Offset 41: Ambient Light Sensor Enable: <b>0=Disable</b>, 2=Enable
+ UINT8 BacklightControlSupport; ///< Offset 42: Backlight Control Support: 0=PWM Inverted, <b>2=PWM Normal</b>
+ UINT8 IgdBootType; ///< Offset 43: IGD Boot Type CMOS option: <b>0=Default</b>, 0x01=CRT, 0x04=EFP, 0x08=LFP, 0x20=EFP3, 0x40=EFP2, 0x80=LFP2
+ UINT32 IuerStatusVal; ///< Offset 44 - 47: Offset 16 This field holds the current status of all the supported Ultrabook events (Intel(R) Ultrabook Event Status bits)
+ CHAR16 GopVersion[0x10]; ///< Offset 48 - 79:This field holds the GOP Driver Version. It is an Output Protocol and updated by the Silicon code
+ /**
+ Offset 80: IGD Panel Type CMOS option\n
+ <b>0=Default</b>, 1=640X480LVDS, 2=800X600LVDS, 3=1024X768LVDS, 4=1280X1024LVDS, 5=1400X1050LVDS1\n
+ 6=1400X1050LVDS2, 7=1600X1200LVDS, 8=1280X768LVDS, 9=1680X1050LVDS, 10=1920X1200LVDS, 13=1600X900LVDS\n
+ 14=1280X800LVDS, 15=1280X600LVDS, 16=2048X1536LVDS, 17=1366X768LVDS
+ **/
+ UINT8 IgdPanelType;
+ UINT8 IgdPanelScaling; ///< Offset 81: IGD Panel Scaling: <b>0=AUTO</b>, 1=OFF, 6=Force scaling
+ UINT8 IgdBlcConfig; ///< Offset 82: Backlight Control Support: 0=PWM Inverted, <b>2=PWM Normal</b>
+ UINT8 IgdBiaConfig; ///< Offset 83: IGD BIA Configuration: <b>0=AUTO</b>, 1=Disabled, 2=Level1, 3=Level2, 4=Level3, 5=Level4, 6=Level5 //@deprecated since Revision2
+ UINT8 IgdSscConfig; ///< Offset 84: IGD SSC Configuration: <b>1=Off</b>, 2=Harware, 3=Software //@deprecated since Revision2
+ UINT8 LowPowerMode; ///< Offset 85: IGD Power Conservation Feature Flag: 0=Disable, <b>2=Enable</b>
+ UINT8 IgdDvmtMemSize; ///< Offset 86: IGD DVMT Memory Size: 1=128MB, <b>2=256MB</b>, 3=MAX
+ UINT8 GfxTurboIMON; ///< Offset 87: IMON Current Value: 14=Minimal, <b>31=Maximum</b>
+} GRAPHICS_DXE_CONFIG;
+#pragma pack(pop)
+
+#endif // _GRAPHICS_DXE_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsPeiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsPeiConfig.h
new file mode 100644
index 0000000000..ee294650bf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/GraphicsPeiConfig.h
@@ -0,0 +1,36 @@
+/** @file
+ Policy definition for Internal Graphics Config Block (PostMem)
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GRAPHICS_PEI_CONFIG_H_
+#define _GRAPHICS_PEI_CONFIG_H_
+#pragma pack(push, 1)
+
+#define GRAPHICS_PEI_CONFIG_REVISION 1
+
+/**
+ This configuration block is to configure IGD related variables used in PostMem PEI.
+ If Intel Gfx Device is not supported, all policies can be ignored.
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ UINT32 PeiGraphicsPeimInit: 1; ///< Offset 28:6 :This policy is used to enable/disable Intel Gfx PEIM.<b>0- Disable</b>, 1- Enable
+ UINT32 RsvdBits0 : 31; ///< Offser 28:16 :Reserved for future use
+ VOID* LogoPtr; ///< Offset 32 Address of Logo to be displayed in PEI
+ UINT32 LogoSize; ///< Offset 36 Logo Size
+ VOID* GraphicsConfigPtr; ///< Offset 40 Address of the Graphics Configuration Table
+} GRAPHICS_PEI_CONFIG;
+#pragma pack(pop)
+
+#endif // _GRAPHICS_PEI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryConfig.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryConfig.h
new file mode 100644
index 0000000000..8f77fa720b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryConfig.h
@@ -0,0 +1,533 @@
+/** @file
+ Policy definition of Memory Config Block
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MEMORY_CONFIG_H_
+#define _MEMORY_CONFIG_H_
+
+#include <SaRegs.h>
+
+#pragma pack(push, 1)
+
+#define SA_MRC_ITERATION_MAX (6)
+#define SA_MRC_MAX_RCOMP (3)
+#define SA_MRC_MAX_RCOMP_TARGETS (5)
+
+#define MEMORY_CONFIG_REVISION 3
+
+///
+/// SMRAM Memory Range
+///
+#define PEI_MR_SMRAM_ABSEG_MASK 0x01
+#define PEI_MR_SMRAM_HSEG_MASK 0x02
+
+///
+/// SA SPD profile selections.
+///
+typedef enum {
+ Default, ///< 0, Default SPD
+ UserDefined, ///< 1, User Defined profile
+ XMPProfile1, ///< 2, XMP Profile 1
+ XMPProfile2 ///< 3, XMP Profile 2
+} SA_SPD;
+
+///
+/// Define the boot modes used by the SPD read function.
+///
+typedef enum {
+ SpdCold, ///< Cold boot
+ SpdWarm, ///< Warm boot
+ SpdS3, ///< S3 resume
+ SpdFast, ///< Fast boot
+ SpdBootModeMax ///< Delimiter
+} SPD_BOOT_MODE;
+
+typedef struct {
+ UINT8 SpdData[SA_MC_MAX_CHANNELS][SA_MC_MAX_SLOTS][SA_MC_MAX_SPD_SIZE];
+//Next Field Offset 2048
+} SPD_DATA_BUFFER;
+
+typedef struct {
+ UINT8 DqByteMap[SA_MC_MAX_CHANNELS][SA_MRC_ITERATION_MAX][2];
+//Next Field Offset 24
+} SA_MEMORY_DQ_MAPPING;
+
+typedef struct {
+ UINT8 DqsMapCpu2Dram[SA_MC_MAX_CHANNELS][SA_MC_MAX_BYTES_NO_ECC];
+//Next Field Offset 16
+} SA_MEMORY_DQS_MAPPING;
+
+typedef struct {
+ UINT16 RcompResistor[SA_MRC_MAX_RCOMP]; ///< Offset 0: Reference RCOMP resistors on motherboard
+ UINT16 RcompTarget[SA_MRC_MAX_RCOMP_TARGETS]; ///< Offset 6: RCOMP target values for DqOdt, DqDrv, CmdDrv, CtlDrv, ClkDrv
+//Next Field Offset 16
+} SA_MEMORY_RCOMP;
+
+typedef struct {
+ UINT16 Start; ///< Offset 0
+ UINT16 End; ///< Offset 2
+ UINT8 BootMode; ///< Offset 4
+ UINT8 Rsvd[3]; ///< Offset 5 Reserved for future use
+} SPD_OFFSET_TABLE;
+
+///
+/// SA memory address decode.
+///
+typedef struct
+{
+ UINT8 Controller; ///< Offset 0 Zero based Controller number
+ UINT8 Channel; ///< Offset 1 Zero based Channel number
+ UINT8 Dimm; ///< Offset 2 Zero based DIMM number
+ UINT8 Rank; ///< Offset 3 Zero based Rank number
+ UINT8 BankGroup; ///< Offset 4 Zero based Bank Group number
+ UINT8 Bank; ///< Offset 5 Zero based Bank number
+ UINT16 Cas; ///< Offset 6 Zero based CAS number
+ UINT32 Ras; ///< Offset 8 Zero based RAS number
+} SA_ADDRESS_DECODE;
+
+typedef UINT8 (EFIAPI * SA_IO_READ_8) (UINTN IoAddress);
+typedef UINT16 (EFIAPI * SA_IO_READ_16) (UINTN IoAddress);
+typedef UINT32 (EFIAPI * SA_IO_READ_32) (UINTN IoAddress);
+typedef UINT8 (EFIAPI * SA_IO_WRITE_8) (UINTN IoAddress, UINT8 Value);
+typedef UINT16 (EFIAPI * SA_IO_WRITE_16) (UINTN IoAddress, UINT16 Value);
+typedef UINT32 (EFIAPI * SA_IO_WRITE_32) (UINTN IoAddress, UINT32 Value);
+typedef UINT8 (EFIAPI * SA_MMIO_READ_8) (UINTN Address);
+typedef UINT16 (EFIAPI * SA_MMIO_READ_16) (UINTN Address);
+typedef UINT32 (EFIAPI * SA_MMIO_READ_32) (UINTN Address);
+typedef UINT64 (EFIAPI * SA_MMIO_READ_64) (UINTN Address);
+typedef UINT8 (EFIAPI * SA_MMIO_WRITE_8) (UINTN Address, UINT8 Value);
+typedef UINT16 (EFIAPI * SA_MMIO_WRITE_16) (UINTN Address, UINT16 Value);
+typedef UINT32 (EFIAPI * SA_MMIO_WRITE_32) (UINTN Address, UINT32 Value);
+typedef UINT64 (EFIAPI * SA_MMIO_WRITE_64) (UINTN Address, UINT64 Value);
+typedef UINT8 (EFIAPI * SA_SMBUS_READ_8) (UINTN Address, RETURN_STATUS *Status);
+typedef UINT16 (EFIAPI * SA_SMBUS_READ_16) (UINTN Address, RETURN_STATUS *Status);
+typedef UINT8 (EFIAPI * SA_SMBUS_WRITE_8) (UINTN Address, UINT8 Value, RETURN_STATUS *Status);
+typedef UINT16 (EFIAPI * SA_SMBUS_WRITE_16) (UINTN Address, UINT16 Value, RETURN_STATUS *Status);
+typedef UINT32 (EFIAPI * SA_GET_PCI_DEVICE_ADDRESS) (UINT8 Bus, UINT8 Device, UINT8 Function, UINT8 Offset);
+typedef UINT32 (EFIAPI * SA_GET_PCIE_DEVICE_ADDRESS) (UINT8 Bus, UINT8 Device, UINT8 Function, UINT8 Offset);
+typedef VOID (EFIAPI * SA_GET_RTC_TIME) (UINT8 *Second, UINT8 *Minute, UINT8 *Hour, UINT8 *Day, UINT8 *Month, UINT16 *Year);
+typedef UINT64 (EFIAPI * SA_GET_CPU_TIME) (VOID *GlobalData);
+typedef VOID * (EFIAPI * SA_MEMORY_COPY) (VOID *Destination, CONST VOID *Source, UINTN NumBytes);
+typedef VOID * (EFIAPI * SA_MEMORY_SET_BYTE) (VOID *Buffer, UINTN NumBytes, UINT8 Value);
+typedef VOID * (EFIAPI * SA_MEMORY_SET_WORD) (VOID *Buffer, UINTN NumWords, UINT16 Value);
+typedef VOID * (EFIAPI * SA_MEMORY_SET_DWORD) (VOID *Buffer, UINTN NumDwords, UINT32 Value);
+typedef UINT64 (EFIAPI * SA_LEFT_SHIFT_64) (UINT64 Data, UINTN NumBits);
+typedef UINT64 (EFIAPI * SA_RIGHT_SHIFT_64) (UINT64 Data, UINTN NumBits);
+typedef UINT64 (EFIAPI * SA_MULT_U64_U32) (UINT64 Multiplicand, UINT32 Multiplier);
+typedef UINT64 (EFIAPI * SA_DIV_U64_U64) (UINT64 Dividend, UINT64 Divisor, UINT64 *Remainder);
+typedef BOOLEAN (EFIAPI * SA_GET_SPD_DATA) (SPD_BOOT_MODE BootMode, UINT8 SpdAddress, UINT8 *Buffer, UINT8 *Ddr3Table, UINT32 Ddr3TableSize, UINT8 *Ddr4Table, UINT32 Ddr4TableSize, UINT8 *LpddrTable, UINT32 LpddrTableSize);
+typedef UINT8 (EFIAPI * SA_GET_MC_ADDRESS_DECODE) (UINT64 Address, SA_ADDRESS_DECODE *DramAddress);
+typedef UINT8 (EFIAPI * SA_GET_MC_ADDRESS_ENCODE) (SA_ADDRESS_DECODE *DramAddress, UINT64 Address);
+typedef BOOLEAN (EFIAPI * SA_GET_RANDOM_NUMBER) (UINT32 *Rand);
+typedef EFI_STATUS (EFIAPI * SA_CPU_MAILBOX_READ) (UINT32 Type, UINT32 Command, UINT32 *Value, UINT32 *Status);
+typedef EFI_STATUS (EFIAPI * SA_CPU_MAILBOX_WRITE) (UINT32 Type, UINT32 Command, UINT32 Value, UINT32 *Status);
+typedef UINT32 (EFIAPI * SA_GET_MEMORY_VDD) (VOID *GlobalData, UINT32 DefaultVdd);
+typedef UINT32 (EFIAPI * SA_SET_MEMORY_VDD) (VOID *GlobalData, UINT32 DefaultVdd, UINT32 Value);
+typedef UINT32 (EFIAPI * SA_CHECKPOINT) (VOID *GlobalData, UINT32 CheckPoint, VOID *Scratch);
+typedef VOID (EFIAPI * SA_DEBUG_HOOK) (VOID *GlobalData, UINT16 DisplayDebugNumber);
+typedef UINT8 (EFIAPI * SA_CHANNEL_EXIST) (VOID *Outputs, UINT8 Channel);
+typedef INT32 (EFIAPI * SA_PRINTF) (VOID *Debug, UINT32 Level, char *Format, ...);
+typedef VOID (EFIAPI * SA_DEBUG_PRINT) (VOID *String);
+typedef UINT32 (EFIAPI * SA_CHANGE_MARGIN) (VOID *GlobalData, UINT8 Param, INT32 Value0, INT32 Value1, UINT8 EnMultiCast, UINT8 Channel, UINT8 RankIn, UINT8 Byte, UINT8 BitIn, UINT8 UpdateMrcData, UINT8 SkipWait, UINT32 RegFileParam);
+typedef UINT8 (EFIAPI * SA_SIGN_EXTEND) (UINT8 Value, UINT8 OldMsb, UINT8 NewMsb);
+typedef VOID (EFIAPI * SA_SHIFT_PI_COMMAND_TRAIN) (VOID *GlobalData, UINT8 Channel, UINT8 Iteration, UINT8 RankMask, UINT8 GroupMask, INT32 NewValue, UINT8 UpdateHost);
+typedef VOID (EFIAPI * SA_UPDATE_VREF_WAIT_STABLE) (VOID *GlobalData, UINT8 VrefType, UINT8 UpdateMrcData, INT32 Offset, UINT8 RankMask, UINT8 DeviceMask, BOOLEAN PDAmode, UINT8 SkipWait);
+typedef UINT8 (EFIAPI * SA_GET_RTC_CMOS) (UINT8 Location);
+typedef UINT64 (EFIAPI * SA_MSR_READ_64) (UINT32 Location);
+typedef UINT64 (EFIAPI * SA_MSR_WRITE_64) (UINT32 Location, UINT64 Data);
+typedef UINT32 (EFIAPI * SA_THERMAL_OVERRIDES) (VOID *GlobalData);
+typedef VOID (EFIAPI * SA_MRC_RETURN_FROM_SMC) (VOID *GlobalData, UINT32 MrcStatus);
+typedef VOID (EFIAPI * SA_MRC_DRAM_RESET) (UINT32 PciEBaseAddress, UINT32 ResetValue);
+typedef VOID (EFIAPI * SA_SET_LOCK_PRMRR) (UINT32 PrmrrBaseAddress, UINT32 PrmrrSize);
+
+
+///
+/// Function calls into the SA.
+///
+typedef struct {
+ SA_IO_READ_8 IoRead8; ///< Offset 0: - CPU I/O port 8-bit read.
+ SA_IO_READ_16 IoRead16; ///< Offset 4: - CPU I/O port 16-bit read.
+ SA_IO_READ_32 IoRead32; ///< Offset 8: - CPU I/O port 32-bit read.
+ SA_IO_WRITE_8 IoWrite8; ///< Offset 12: - CPU I/O port 8-bit write.
+ SA_IO_WRITE_16 IoWrite16; ///< Offset 16: - CPU I/O port 16-bit write.
+ SA_IO_WRITE_32 IoWrite32; ///< Offset 20: - CPU I/O port 32-bit write.
+ SA_MMIO_READ_8 MmioRead8; ///< Offset 24: - Memory Mapped I/O port 8-bit read.
+ SA_MMIO_READ_16 MmioRead16; ///< Offset 28: - Memory Mapped I/O port 16-bit read.
+ SA_MMIO_READ_32 MmioRead32; ///< Offset 32: - Memory Mapped I/O port 32-bit read.
+ SA_MMIO_READ_64 MmioRead64; ///< Offset 36: - Memory Mapped I/O port 64-bit read.
+ SA_MMIO_WRITE_8 MmioWrite8; ///< Offset 40: - Memory Mapped I/O port 8-bit write.
+ SA_MMIO_WRITE_16 MmioWrite16; ///< Offset 44: - Memory Mapped I/O port 16-bit write.
+ SA_MMIO_WRITE_32 MmioWrite32; ///< Offset 48: - Memory Mapped I/O port 32-bit write.
+ SA_MMIO_WRITE_64 MmioWrite64; ///< Offset 52: - Memory Mapped I/O port 64-bit write.
+ SA_SMBUS_READ_8 SmbusRead8; ///< Offset 56: - Smbus 8-bit read.
+ SA_SMBUS_READ_16 SmbusRead16; ///< Offset 60: - Smbus 16-bit read.
+ SA_SMBUS_WRITE_8 SmbusWrite8; ///< Offset 64: - Smbus 8-bit write.
+ SA_SMBUS_WRITE_16 SmbusWrite16; ///< Offset 68: - Smbus 16-bit write.
+ SA_GET_PCI_DEVICE_ADDRESS GetPciDeviceAddress; ///< Offset 72: - Get PCI device address.
+ SA_GET_PCIE_DEVICE_ADDRESS GetPcieDeviceAddress; ///< Offset 76: - Get PCI express device address.
+ SA_GET_RTC_TIME GetRtcTime; ///< Offset 80: - Get the current time value.
+ SA_GET_CPU_TIME GetCpuTime; ///< Offset 84: - The current CPU time in milliseconds.
+ SA_MEMORY_COPY CopyMem; ///< Offset 88: - Perform byte copy operation.
+ SA_MEMORY_SET_BYTE SetMem; ///< Offset 92: - Perform byte initialization operation.
+ SA_MEMORY_SET_WORD SetMemWord; ///< Offset 96: - Perform word initialization operation.
+ SA_MEMORY_SET_DWORD SetMemDword; ///< Offset 100: - Perform dword initialization operation.
+ SA_LEFT_SHIFT_64 LeftShift64; ///< Offset 104: - Left shift the 64-bit data value by specified number of bits.
+ SA_RIGHT_SHIFT_64 RightShift64; ///< Offset 108: - Right shift the 64-bit data value by specified number of bits.
+ SA_MULT_U64_U32 MultU64x32; ///< Offset 112: - Multiply a 64-bit data value by a 32-bit data value.
+ SA_DIV_U64_U64 DivU64x64; ///< Offset 116: - Divide a 64-bit data value by a 64-bit data value.
+ SA_GET_SPD_DATA GetSpdData; ///< Offset 120: - Read the SPD data over the SMBus, at the given SmBus SPD address and copy the data to the data structure.
+ SA_GET_RANDOM_NUMBER GetRandomNumber; ///< Offset 124: - Get the next random 32-bit number.
+ SA_CPU_MAILBOX_READ CpuMailboxRead; ///< Offset 128: - Perform a CPU mailbox read.
+ SA_CPU_MAILBOX_WRITE CpuMailboxWrite; ///< Offset 132: - Perform a CPU mailbox write.
+ SA_GET_MEMORY_VDD GetMemoryVdd; ///< Offset 136: - Get the current memory voltage (VDD).
+ SA_SET_MEMORY_VDD SetMemoryVdd; ///< Offset 140: - Set the memory voltage (VDD) to the given value.
+ SA_CHECKPOINT CheckPoint; ///< Offset 144: - Check point that is called at various points in the MRC.
+ SA_DEBUG_HOOK DebugHook; ///< Offset 148: - Typically used to display to the I/O port 80h.
+ SA_DEBUG_PRINT DebugPrint; ///< Offset 152: - Output a string to the debug stream/device.
+ SA_GET_RTC_CMOS GetRtcCmos; ///< Offset 156: - Get the current value of the specified RTC CMOS location.
+ SA_MSR_READ_64 ReadMsr64; ///< Offset 160: - Get the current value of the specified MSR location.
+ SA_MSR_WRITE_64 WriteMsr64; ///< Offset 164 - Set the current value of the specified MSR location.
+ SA_MRC_RETURN_FROM_SMC MrcReturnFromSmc; ///< Offset 168 - Hook function after returning from MrcStartMemoryConfiguration()
+ SA_MRC_DRAM_RESET MrcDramReset; ///< Offset 172 - Assert or deassert DRAM_RESET# pin; this is used in JEDEC Reset.
+} SA_FUNCTION_CALLS;
+
+///
+/// Function calls into the MRC.
+///
+typedef struct {
+ SA_GET_MC_ADDRESS_DECODE GetMcAddressDecode; ///< Offset 0: - Converts system address to DRAM address.
+ SA_GET_MC_ADDRESS_ENCODE GetMcAddressEncode; ///< Offset 4: - Converts DRAM address to system address.
+ SA_CHANNEL_EXIST MrcChannelExist; ///< Offset 8: - Returns whether Channel is or is not present.
+ SA_PRINTF MrcPrintf; ///< Offset 12: - Print to output stream/device.
+ SA_CHANGE_MARGIN MrcChangeMargin; ///< Offset 16: - Change the margin.
+ SA_SIGN_EXTEND MrcSignExtend; ///< Offset 20: - Sign extends OldMSB to NewMSB Bits (Eg: Bit 6 to Bit 7).
+ SA_SHIFT_PI_COMMAND_TRAIN ShiftPiCommandTrain; ///< Offset 24: - Move CMD/CTL/CLK/CKE PIs during training.
+ SA_UPDATE_VREF_WAIT_STABLE UpdateVrefWaitStable; ///< Offset 28: - Update the Vref value and wait until it is stable.
+ SA_THERMAL_OVERRIDES MrcThermalOverrides; ///< Offset 32: - Update memory thermal conditions.
+} SA_MEMORY_FUNCTIONS;
+
+/**
+ Memory Configuration
+ The contents of this structure are CRC'd by the MRC for option change detection.
+ This structure is copied en mass to the MrcInput structure.
+ If you add fields here, you must update the MrcInput structure.\n
+ <b>Revision 1</b>:
+ - Initial version.
+
+ <b>Revision 2</b>:
+ - Added CMDSR, CMDDSEQ and CMDNORM.
+ - Added Ddr4DdpSharedClock and Ddr4DdpSharedZq.
+
+ <b>Revision 3</b>:
+ - Added EWRDSEQ.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ UINT8 HobBufferSize; ///< Offset 28 Size of HOB buffer for MRC
+ //
+ // The following parameters are used only when SpdProfileSelected is UserDefined (CUSTOM PROFILE)
+ //
+ UINT8 SpdProfileSelected; ///< Offset 29 SPD XMP profile selection - for XMP supported DIMM: <b>0=Default DIMM profile</b>, 1=Customized profile, 2=XMP profile 1, 3=XMP profile 2.
+ UINT16 tCL; ///< Offset 30 User defined Memory Timing tCL value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 31=Maximum.
+ UINT16 tRCDtRP; ///< Offset 32 User defined Memory Timing tRCD value (same as tRP), valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 63=Maximum.
+ UINT16 tRAS; ///< Offset 34 User defined Memory Timing tRAS value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 64=Maximum.
+ UINT16 tWR; ///< Offset 36 User defined Memory Timing tWR value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, legal values: 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24.
+ UINT16 tRFC; ///< Offset 38 User defined Memory Timing tRFC value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 1023=Maximum.
+ UINT16 tRRD; ///< Offset 40 User defined Memory Timing tRRD value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 15=Maximum.
+ UINT16 tWTR; ///< Offset 42 User defined Memory Timing tWTR value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 28=Maximum.
+ UINT16 tRTP; ///< Offset 44 User defined Memory Timing tRTP value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 15=Maximum. DDR4 legal values: 5, 6, 7, 8, 9, 10, 12
+ UINT16 tFAW; ///< Offset 46 User defined Memory Timing tFAW value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 63=Maximum.
+ UINT16 tCWL; ///< Offset 48 User defined Memory Timing tCWL value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 20=Maximum.
+ UINT16 tREFI; ///< Offset 50 User defined Memory Timing tREFI value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 65535=Maximum.
+ UINT16 VddVoltage; ///< Offset 52 DRAM voltage (Vdd) in millivolts: <b>0=Platform Default (no override)</b>, 1200=1.2V, 1350=1.35V etc.
+ UINT8 NModeSupport; ///< Offset 54 Memory N Mode Support - Enable user to select Auto, 1N or 2N: <b>0=AUTO</b>, 1=1N, 2=2N.
+
+ UINT8 McLock; ///< Offset 55 Enable/Disable memory configuration register locking: 0=Disable, <b>1=Enable</b>.
+ //
+ // Thermal Management
+ //
+ UINT32 ThermalManagement:1; ///< Offset 56 Memory Thermal Management Support: <b>0=Disable</b>, 1=Enable.
+ UINT32 PeciInjectedTemp:1; ///< - Enable/Disable memory temperatures to be injected to the processor via PECI: <b>0=Disable</b>, 1=Enable.
+ UINT32 ExttsViaTsOnBoard:1; ///< - Enable/Disable routing TS-on-Board's ALERT# and THERM# to EXTTS# pins on the PCH: <b>0=Disable</b>, 1=Enable.
+ UINT32 ExttsViaTsOnDimm:1; ///< - Enable/Disable routing TS-on-DIMM's ALERT# to EXTTS# pin on the PCH: <b>0=Disable</b>, 1=Enable.
+ UINT32 VirtualTempSensor:1; ///< - Enable/Disable Virtual Temperature Sensor (VTS): <b>0=Disable</b>, 1=Enable.
+ UINT32 RsvdBits0:27;
+ //
+ // Training Algorithms
+ //
+ UINT32 ECT:1; ///< Offset 60 Enable/Disable Early Command Training. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable.
+ UINT32 SOT:1; ///< - Enable/Disable Sense Amp Offset Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 ERDMPRTC2D:1; ///< - Enable/Disable Early ReadMPR Timing Centering 2D. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 RDMPRT:1; ///< - Enable/Disable Read MPR Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 RCVET:1; ///< - Enable/Disable Receive Enable Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 JWRL:1; ///< - Enable/Disable JEDEC Write Leveling Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 EWRTC2D:1; ///< - Enable/Disable Early Write Time Centering 2D Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 ERDTC2D:1; ///< - Enable/Disable Early Read Time Centering 2D Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 WRTC1D:1; ///< - Enable/Disable 1D Write Timing Centering Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 WRVC1D:1; ///< - Enable/Disable 1D Write Voltage Centering Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 RDTC1D:1; ///< - Enable/Disable 1D Read Timing Centering Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 DIMMODTT:1; ///< - Enable/Disable DIMM ODT Training. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable.
+ UINT32 DIMMRONT:1; ///< - Enable/Disable DIMM RON training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 WRDSEQT:1; ///< - Enable/Disable Write Drive Strength / Equalization Training 2D. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable.
+ UINT32 WRSRT:1; ///< - Enable/Disable Write Slew Rate traning. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable.</b>
+ UINT32 RDODTT:1; ///< - Enable/Disable Read ODT Training. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable.
+ UINT32 RDEQT:1; ///< - Enable/Disable Read Equalization Training. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable.
+ UINT32 RDAPT:1; ///< - Enable/Disable Read Amplifier Power Training. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable.
+ UINT32 WRTC2D:1; ///< - Enable/Disable 2D Write Timing Centering Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 RDTC2D:1; ///< - Enable/Disable 2D Read Timing Centering Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 WRVC2D:1; ///< - Enable/Disable 2D Write Voltage Centering Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 RDVC2D:1; ///< - Enable/Disable 2D Read Voltage Centering Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 CMDVC:1; ///< - Enable/Disable Command Vref Centering Training. Note it is not recommended to change this setting from the default value 0=Disable, <b>1=Enable</b>.
+ UINT32 LCT:1; ///< - Enable/Disable Late Command Training. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 RTL:1; ///< - Enable/Disable Round Trip Latency function. Note it is not recommended to change this setting from the default value: 0=Disable, <b>1=Enable</b>.
+ UINT32 TAT:1; ///< - Enable/Disable Turn Around Time function. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable.
+ UINT32 RMT:1; ///< - Enable/Disable Rank Margin Tool function: <b>0=Disable</b>, 1=Enable.
+ UINT32 MEMTST:1; ///< - Enable/Disable Memory Test function: <b>0=Disable</b>, 1=Enable.
+ UINT32 ALIASCHK:1; ///< - Enable/Disable DIMM SPD Alias Check: 0=Disable, <b>1=Enable</b>
+ UINT32 RCVENC1D:1; ///< - Enable/Disable Receive Enable Centering Training (LPDDR Only). Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable
+ UINT32 RMC:1; ///< - Enable/Disable Retrain Margin Check. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable
+ UINT32 WRDSUDT:1; ///< - Enable/Disable Write Drive Strength Up/Dn independently. Note it is not recommended to change this setting from the default value: <b>0=Disable</b>, 1=Enable
+
+ UINT32 MrcSafeConfig:1; ///< Offset 64 MRC Safe Mode: <b>0=Disable</b>, 1=Enable
+ UINT32 EccSupport:1; ///< - DIMM Ecc Support option - for Desktop only: 0=Disable, <b>1=Enable</b>
+ UINT32 RemapEnable:1; ///< - This option is used to control whether to enable/disable memory remap above 4GB: 0=Disable, <b>1=Enable</b>.
+ UINT32 ScramblerSupport:1; ///< - Memory scrambler support: 0=Disable, <b>1=Enable</b>
+ UINT32 OddRatioMode:1; ///< - If Odd Ratio Mode is enabled, QCLK frequency has an addition of 133/100 MHz: <b>0=Disable</b>, 1=Enable
+ UINT32 MrcTimeMeasure:1; ///< - Enables serial debug level to display the MRC execution times only: <b>0=Disable</b>, 1=Enable
+ UINT32 MrcFastBoot:1; ///< - Enables the MRC fast boot path for faster cold boot execution: 0=Disable, <b>1=Enable</b>
+ UINT32 DqPinsInterleaved:1; ///< - Interleaving mode of DQ/DQS pins for HSW_ULT which depends on board routing: <b>0=Disable</b>, 1=Enable
+ UINT32 RankInterleave:1; ///< - Rank Interleave Mode: 0=Disable, <b>1=Enable</b>
+ UINT32 EnhancedInterleave:1; ///< - Enhanced Interleave Mode: 0=Disable, <b>1=Enable</b>
+ UINT32 WeaklockEn:1; ///< - Weak Lock Enable: 0=Disable, <b>1=Enable</b>
+ UINT32 CmdTriStateDis:1; ///< - CMD Tri-State Support: <b>0=Enable</b>, 1=Disable. Note: This should be set to 1 (Disable) if Command RTT is not present on the platform.
+ UINT32 MemoryTrace:1; ///< - Memory Trace to second DDR channel using Stacked Mode: <b>0=Disable</b>, 1=Enable
+ UINT32 ChHashEnable:1; ///< - Channel Hash Enable: 0=Disable, <b>1=Enable</b>
+ UINT32 EnableExtts:1; ///< - Enable Extts: <b>0=Disable</b>, 1=Enable
+ UINT32 EnableCltm:1; ///< - Enable Closed Loop Thermal Management: <b>0=Disable</b>, 1=Enable
+ UINT32 EnableOltm:1; ///< - Enable Open Loop Thermal Management: <b>0=Disable</b>, 1=Enable
+ UINT32 EnablePwrDn:1; ///< - Enable Power Down control for DDR: 0=PCODE control, <b>1=BIOS control</b>
+ UINT32 EnablePwrDnLpddr:1; ///< - Enable Power Down for LPDDR: 0=PCODE control, <b>1=BIOS control</b>
+ UINT32 LockPTMregs:1; ///< - Lock PCU Thermal Management registers: 0=Disable, <b>1=Enable</b>
+ UINT32 UserPowerWeightsEn:1; ///< - Allows user to explicitly set power weight, scale factor, and channel power floor values: <b>0=Disable</b>, 1=Enable
+ UINT32 RaplLim2Lock:1; ///< - Lock DDR_RAPL_LIMIT register: <b>0=Disable</b>, 1=Enable
+ UINT32 RaplLim2Ena:1; ///< - Enable Power Limit 2: <b>0=Disable</b>, 1=Enable
+ UINT32 RaplLim1Ena:1; ///< - Enable Power Limit 1: <b>0=Disable</b>, 1=Enable
+ UINT32 SrefCfgEna:1; ///< - Enable Self Refresh: 0=Disable, <b>1=Enable</b>
+ UINT32 ThrtCkeMinDefeatLpddr:1; ///< - Throttler CKE min defeature for LPDDR: 0=Disable, <b>1=Enable</b>
+ UINT32 ThrtCkeMinDefeat:1; ///< - Throttler CKE min defeature: <b>0=Disable</b>, 1=Enable
+ UINT32 AutoSelfRefreshSupport:1; ///< - FALSE = No auto self refresh support, <b>TRUE = auto self refresh support</b>
+ UINT32 ExtTemperatureSupport:1; ///< - FALSE = No extended temperature support, <b>TRUE = extended temperature support</b>
+ UINT32 MobilePlatform:1; ///< - Memory controller device id indicates: <b>TRUE if mobile</b>, FALSE if not. Note: This will be auto-detected and updated.
+ UINT32 Force1Dpc:1; ///< - TRUE means force one DIMM per channel, <b>FALSE means no limit</b>
+ UINT32 ForceSingleRank:1; ///< - TRUE means use Rank0 only (in each DIMM): <b>0=Disable</b>, 1=Enable
+
+ UINT32 RhPrevention:1; ///< Offset 68 RH Prevention Enable/Disable: 0=Disable, <b>1=Enable</b>
+ UINT32 VttTermination:1; ///< - Vtt Termination for Data ODT: <b>0=Disable</b>, 1=Enable
+ UINT32 VttCompForVsshi:1; ///< - Enable/Disable Vtt Comparator For Vsshi: <b>0=Disable</b>, 1=Enable
+ UINT32 ExitOnFailure:1; ///< - MRC option for exit on failure or continue on failure: 0=Disable, <b>1=Enable</b>
+ UINT32 Vc1ReadMeter:1; ///< - VC1 Read Metering Enable: 0=Disable, <b>1=Enable</b>
+ UINT32 DdrThermalSensor:1; ///< - Ddr Thermal Sensor: 0=Disable, <b>1=Enable</b>
+ UINT32 LpddrMemWriteLatencySet:1; ///< - LPDDR3 Write Latency Set option: 0=Set A, <b>1=Set B</b>
+ UINT32 EvLoader:1; ///< - Option to Enable EV Loader: <b>0=Disable</b>,1=Enable
+ UINT32 EvLoaderDelay:1; ///< - Option to Enable EV Loader Delay: 0=Disable, <b>1=Enable</b>
+ UINT32 Ddr4DdpSharedClock:1; ///< - Select if CLK0 is shared between Rank0 and Rank1 in DDR4 DDP package. <b>0=Not shared</b>, 1=Shared
+ UINT32 Ddr4DdpSharedZq:1; ///< - Select if ZQ pin is shared between Rank0 and Rank1 in DDR4 DDP package. <b>0=Not shared</b>, 1=Shared
+ UINT32 RsvdBits1:21;
+
+ UINT32 BClkFrequency; ///< Offset 72 - Base reference clock value, in Hertz: <b>100000000 = 100Hz</b>, 125000000=125Hz, 167000000=167Hz, 250000000=250Hz
+ UINT16 DdrFreqLimit; ///< Offset 76 Memory Frequency Limit: <b>0=Auto (limited by SPD/CPU capability)</b>, for valid values see MrcFrequency in MrcInterface.h
+ /**
+ Selects the DDR base reference clock\n
+ <b>0x00 = 133MHz</b>
+ 0x01 = 100MHz
+ **/
+ UINT8 RefClk; ///< Offset 78
+ /**
+ Selects the ratio to multiply the reference clock by for the DDR frequency\n
+ When RefClk is 133MHz\n
+ <b>0x00 = Auto</b>, 0x03 through 0x0C are valid values, all others are invalid\n
+ When RefClk is 100MHz\n
+ <b>0x00 = Auto</b>, 0x06 through 0x10 are valid values, all others are invalid\n
+ **/
+ UINT8 Ratio; ///< Offset 79
+ UINT8 ProbelessTrace; ///< Offset 80 Probeless Trace: <b>0=Disabled</b>, 1=GDXC IOT/MOT, 2=HD Port. <b>Note: Enabling ProbelessTrace will also need enabling IED together.</b>
+ UINT8 GdxcIotSize; ///< Offset 81 GDXC IOT Size in 8MB granularity: 0=Minimal, 128=Maximum, <b>4=32MB</b>.
+ UINT8 GdxcMotSize; ///< Offset 82 GDXC MOT Size in 8MB granularity: 0=Minimal, 128=Maximum, <b>12=96MB</b>.
+ /**
+ - Channel Hash Enable.\n
+ NOTE: BIT7 will interlave the channels at a 2 cacheline granularity, BIT8 at 4 and BIT9 at 8\n
+ 0=BIT6, <B>1=BIT7</B>, 2=BIT8, 3=BIT9
+ **/
+ UINT8 ChHashInterleaveBit; ///< Offset 83
+ UINT16 ChHashMask; ///< Offset 84 - Channel Hash Mask: 0x0001=BIT6 set(Minimal), 0x3FFF=BIT[19:6] set(Maximum), <b>0x30CE= BIT[19:18, 13:12 ,9:7] set</b>
+ /**
+ Disables a DIMM slot in the channel even if a DIMM is present\n
+ Array index represents the channel number (0 = channel 0, 1 = channel 1)\n
+ <b>0x0 = DIMM 0 and DIMM 1 enabled</b>\n
+ 0x1 = DIMM 0 disabled, DIMM 1 enabled\n
+ 0x2 = DIMM 0 enabled, DIMM 1 disabled\n
+ 0x3 = DIMM 0 and DIMM 1 disabled (will disable the whole channel)\n
+ **/
+ UINT8 DisableDimmChannel[SA_MC_MAX_CHANNELS];///< Offset 86
+
+ UINT8 RaplLim2WindX; ///< Offset 88 - Power Limit 2 Time Window X value: 0=Minimal, 3=Maximum, <b>1=Default</b>
+ UINT8 RaplLim2WindY; ///< Offset 89 - Power Limit 2 Time Window Y value: 0=Minimal, 3=Maximum, <b>1=Default</b>
+ UINT8 RaplLim1WindX; ///< Offset 90 - Power Limit 1 Time Window X value: <b>0=Minimal</b>, 3=Maximum
+ UINT8 RaplLim1WindY; ///< Offset 91 - Power Limit 1 Time Window Y value: <b>0=Minimal</b>, 31=Maximum
+ UINT16 RaplLim2Pwr; ///< Offset 92 - Power Limit 2: 0=Minimal, 16383=Maximum, <b>222=Default</b>
+ UINT16 RaplLim1Pwr; ///< Offset 94 - Power Limit 1: <b>0=Minimal</b>, 16383=Maximum
+ UINT8 WarmThresholdCh0Dimm0; ///< Offset 96 - Warm Threshold (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmThresholdCh0Dimm1; ///< Offset 97 - Warm Threshold (Channel 0, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmThresholdCh1Dimm0; ///< Offset 98 - Warm Threshold (Channel 1, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmThresholdCh1Dimm1; ///< Offset 99 - Warm Threshold (Channel 1, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotThresholdCh0Dimm0; ///< Offset 100 - Hot Threshold (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotThresholdCh0Dimm1; ///< Offset 101 - Hot Threshold (Channel 0, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotThresholdCh1Dimm0; ///< Offset 102 - Hot Threshold (Channel 1, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotThresholdCh1Dimm1; ///< Offset 103 - Hot Threshold (Channel 1, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmBudgetCh0Dimm0; ///< Offset 104 - Warm Budget (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmBudgetCh0Dimm1; ///< Offset 105 - Warm Budget (Channel 0, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmBudgetCh1Dimm0; ///< Offset 106 - Warm Budget (Channel 1, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmBudgetCh1Dimm1; ///< Offset 107 - Warm Budget (Channel 1, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotBudgetCh0Dimm0; ///< Offset 108 - Hot Budget (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotBudgetCh0Dimm1; ///< Offset 109 - Hot Budget (Channel 0, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotBudgetCh1Dimm0; ///< Offset 110 - Hot Budget (Channel 1, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotBudgetCh1Dimm1; ///< Offset 111 - Hot Budget (Channel 1, Dimm 1): 0=Minimal, <b>255=Maximum</b>
+ UINT8 IdleEnergyCh0Dimm0; ///< Offset 113 - Idle Energy (Channel 0, Dimm 0): 0=Minimal, 63=Maximum, <b>10=Default</b>
+ UINT8 IdleEnergyCh0Dimm1; ///< Offset 112 - Idle Energy (Channel 0, Dimm 1): 0=Minimal, 63=Maximum, <b>10=Default</b>
+ UINT8 IdleEnergyCh1Dimm0; ///< Offset 115 - Idle Energy (Channel 1, Dimm 0): 0=Minimal, 63=Maximum, <b>10=Default</b>
+ UINT8 IdleEnergyCh1Dimm1; ///< Offset 114 - Idle Energy (Channel 1, Dimm 1): 0=Minimal, 63=Maximum, <b>10=Default</b>
+ UINT8 PdEnergyCh0Dimm0; ///< Offset 117 - Power Down Energy (Channel 0, Dimm 0): 0=Minimal, 63=Maximum, <b>6=Default</b>
+ UINT8 PdEnergyCh0Dimm1; ///< Offset 116 - Power Down Energy (Channel 0, Dimm 1): 0=Minimal, 63=Maximum, <b>6=Default</b>
+ UINT8 PdEnergyCh1Dimm0; ///< Offset 119 - Power Down Energy (Channel 1, Dimm 0): 0=Minimal, 63=Maximum, <b>6=Default</b>
+ UINT8 PdEnergyCh1Dimm1; ///< Offset 118 - Power Down Energy (Channel 1, Dimm 1): 0=Minimal, 63=Maximum, <b>6=Default</b>
+ UINT8 ActEnergyCh0Dimm0; ///< Offset 121 - Activation Energy (Channel 0, Dimm 0): 0=Minimal, 255=Maximum, <b>172=Default</b>
+ UINT8 ActEnergyCh0Dimm1; ///< Offset 120 - Activation Energy (Channel 0, Dimm 1): 0=Minimal, 255=Maximum, <b>172=Default</b>
+ UINT8 ActEnergyCh1Dimm0; ///< Offset 123 - Activation Energy (Channel 1, Dimm 0): 0=Minimal, 255=Maximum, <b>172=Default</b>
+ UINT8 ActEnergyCh1Dimm1; ///< Offset 122 - Activation Energy (Channel 1, Dimm 1): 0=Minimal, 255=Maximum, <b>172=Default</b>
+ UINT8 RdEnergyCh0Dimm0; ///< Offset 125 - Read Energy (Channel 0, Dimm 0): 0=Minimal, 255=Maximum, <b>212=Default</b>
+ UINT8 RdEnergyCh0Dimm1; ///< Offset 124 - Read Energy (Channel 0, Dimm 1): 0=Minimal, 255=Maximum, <b>212=Default</b>
+ UINT8 RdEnergyCh1Dimm0; ///< Offset 127 - Read Energy (Channel 1, Dimm 0): 0=Minimal, 255=Maximum, <b>212=Default</b>
+ UINT8 RdEnergyCh1Dimm1; ///< Offset 126 - Read Energy (Channel 1, Dimm 1): 0=Minimal, 255=Maximum, <b>212=Default</b>
+ UINT8 WrEnergyCh0Dimm0; ///< Offset 129 - Write Energy (Channel 0, Dimm 0): 0=Minimal, 255=Maximum, <b>221=Default</b>
+ UINT8 WrEnergyCh0Dimm1; ///< Offset 128 - Write Energy (Channel 0, Dimm 1): 0=Minimal, 255=Maximum, <b>221=Default</b>
+ UINT8 WrEnergyCh1Dimm0; ///< Offset 131 - Write Energy (Channel 1, Dimm 0): 0=Minimal, 255=Maximum, <b>221=Default</b>
+ UINT8 WrEnergyCh1Dimm1; ///< Offset 130 - Write Energy (Channel 1, Dimm 1): 0=Minimal, 255=Maximum, <b>221=Default</b>
+
+ UINT16 SrefCfgIdleTmr; ///< Offset 132 - Self Refresh idle timer: <b>512=Minimal</b>, 65535=Maximum
+ UINT8 MaxRttWr; ///< Offset 134 - Maximum DIMM RTT_WR to use in power training: <b>0=ODT Off</b>, 1 = 120 ohms
+ UINT8 ThrtCkeMinTmr; ///< Offset 135 - Throttler CKE min timer: 0=Minimal, 0xFF=Maximum, <b>0x30=Default</b>
+ UINT8 ThrtCkeMinTmrLpddr; ///< Offset 136 - Throttler CKE min timer for LPDDR: 0=Minimal, 0xFF=Maximum, <b>0x40=Default</b>
+
+ UINT8 EnergyScaleFact; ///< Offset 137 - Energy Scale Factor. 0=Minimal, 7=Maximum, <b>4=Default</b>
+ UINT8 RaplPwrFlCh1; ///< Offset 138 - Power Channel 1 Floor value: <b>0=Minimal</b>, 255=Maximum
+ UINT8 RaplPwrFlCh0; ///< Offset 139 - Power Channel 0 Floor value: <b>0=Minimal</b>, 255=Maximum
+ UINT8 PowerDownMode; ///< Offset 140 - CKE Power Down Mode: <b>0xFF=AUTO</b>, 0=No Power Down, 1= APD mode, 6=PPD-DLL Off mode
+ UINT8 PwdwnIdleCounter; ///< Offset 141 - CKE Power Down Mode Idle Counter: 0=Minimal, 255=Maximum, <b>0x80=0x80 DCLK</b>
+ UINT8 CkeRankMapping; ///< Offset 142 - Bits [7:4] - Channel 1, bits [3:0] - Channel 0. <b>0xAA=Default</b> Bit [i] specifies which rank CKE[i] goes to.
+ UINT8 BerEnable; ///< Offset 143 - BER Enable and # of Addresses passed in: <b>0=Minimal</b>, 8=Maximum
+ UINT64 BerAddress[4]; ///< Offset 144 - BER Address(es): <b>0=Minimal</b>, 0xFFFFFFFFFFFFFFFF=Maximum (step is 0x40)
+ UINT16 PciIndex; ///< Offset 176 - Pci index register address: <b>0xCF8=Default</b>
+ UINT16 PciData; ///< Offset 178 - Pci data register address: <b>0xCFC=Default</b>
+
+ UINT8 StrongWkLeaker; ///< Offset 180 - Strong Weak Leaker: 1=Minimal, <b>7=Maximum</b>
+ UINT8 CaVrefConfig; ///< Offset 181 0=VREF_CA goes to both CH_A and CH_B, 1=VREF_CA to CH_A, VREF_DQ_A to CH_B, <b>2=VREF_CA to CH_A, VREF_DQ_B to CH_B</b>
+ UINT16 FreqSaGvLow; ///< Offset 182 SA GV Low: 0 is Auto/default, otherwise holds the frequency value: <b>0=Default</b>, 1067, 1200, 1333, 1400, 1600, 1800, 1867. NOTE: must be below or equal to the SA GV High frequency.
+ UINT32 Vc1ReadMeterTimeWindow; ///< Offset 184 - VC1 Read Meter Time Window: 0=Minimal, 0x1FFFF=Maximum, <b>0x320=Default</b>
+ UINT16 Vc1ReadMeterThreshold; ///< Offset 188 - VC1 Read Meter Threshold (within Time Window): 0=Minimal, 0xFFFF=Maximum, <b>0x118=Default</b>
+ UINT16 Idd3n; ///< Offset 190 EPG Active standby current (Idd3N) in milliamps from DIMM datasheet.
+ UINT16 Idd3p; ///< Offset 192 EPG Active power-down current (Idd3P) in milliamps from DIMM datasheet.
+ UINT8 EpgEnable; ///< Offset 194 Enable Energy Performance Gain.
+ UINT8 RhSolution; ///< Offset 195 Type of solution to be used for RHP - 0/1 = HardwareRhp/Refresh2x
+ UINT8 RhActProbability; ///< Offset 196 Activation probability for Hardware RHP
+ UINT8 SaGv; ///< Offset 197 SA GV: <b>0=Disabled</b>, 1=FixedLow, 2=FixedHigh, 3=Enabled
+
+ UINT8 UserThresholdEnable; ///< Offset 198 - Flag to manually select the DIMM CLTM Thermal Threshold, 0=Disable, 1=Enable, <b>0=Default</b>
+ UINT8 UserBudgetEnable; ///< Offset 199 - Flag to manually select the Budget Regiseters for CLTM Memory Dimms , 0=Disable, 1=Enable, <b>0=Default</b>
+ UINT8 TsodTcritMax; ///< Offset 200 - TSOD Tcrit Maximum Value to be Configure , 0=Minimal, 128=Maximum, , <b>105=Default</b>
+ UINT8 TsodEventMode; ///< Offset 201 - Flag to Enable Event Mode Interruption in TSOD Configuration Register, 0=Disable, 1=Enable, <b>1=Default</b>
+ UINT8 TsodEventPolarity; ///< Offset 202 - Event Signal Polarity in TSOD Configuration Register, 0=Low, 1=High, <b>0=Default</b>
+ UINT8 TsodCriticalEventOnly; ///< Offset 203 - Critical Trigger Only in TSOD Configuration Register,0=Disable, 1=Enable, <b>1=Default</b>
+ UINT8 TsodEventOutputControl; ///< Offset 204 - Event Output Control in TSOD Configuration Register,0=Disable, 1=Enable, <b>1=Default</b>
+ UINT8 TsodAlarmwindowLockBit; ///< Offset 205 - Alarm Windows Lock Bit in TSOD Configuration Register,0=Unlock, 1=Lock, <b>0=Default</b>
+ UINT8 TsodCriticaltripLockBit;///< Offset 206 - Critical Trip Lock Bit in TSOD Configuration Register,0=Unlock, 1=Lock, <b>0=Default</b>
+ UINT8 TsodShutdownMode; ///< Offset 207 - Shutdown Mode TSOD Configuration Register,0=Enable, 1=Disable, <b>0=Default</b>
+ UINT8 TsodThigMax; ///< Offset 208 - Thigh Max Value In the for CLTM Memory Dimms , 0=Disable, 1=Enable, <b>0=Default</b>
+ UINT8 TsodManualEnable; ///< Offset 209 - Flag to manually select the TSOD Register Values , 0=Disable, 1=Enable, <b>0=Default</b>
+
+ UINT8 RetrainOnFastFail; ///< Offset 210 - Restart MRC in Cold mode if SW MemTest fails during Fast flow. 0 = Disabled, <b>1 = Enabled</b>
+ UINT8 ForceOltmOrRefresh2x; ///< Offset 211 - Force OLTM or 2X Refresh when needed. <b>0 = Force OLTM</b>, 1 = Force 2x Refresh
+ UINT8 DllBwEn0; ///< Offset 212 - DllBwEn value for 1067
+ UINT8 DllBwEn1; ///< Offset 213 - DllBwEn value for 1333
+ UINT8 DllBwEn2; ///< Offset 214 - DllBwEn value for 1600
+ UINT8 DllBwEn3; ///< Offset 215 - DllBwEn value for 1867 and up
+ UINT32 VddSettleWaitTime; ///< Offset 216 - Amount of time in microseconds to wait for Vdd to settle on top of 200us required by JEDEC spec: <b>Default=0</b>
+ UINT8 EnCmdRate; ///< Offset 220 - CMD Rate Enable: 0=Disable, 1=1 CMD, 2=2 CMDs, <b>3=3 CMDs</b>, 4=4 CMDs, 5=5 CMDs, 6=6 CMDs, 7=7 CMDs
+ UINT8 Refresh2X; ///< Offset 221 - Refresh 2x: <b>0=Disable</b>, 1=Enable for WARM or HOT, 2=Enable for HOT only
+ UINT8 SmramMask; ///< Offset 222 Reserved memory ranges for SMRAM
+ UINT8 Rsvd0; ///< Offset 223 - Reserved.
+
+ //
+ // Training Algorithms
+ //
+ UINT32 CMDSR : 1; ///< Offset 224 - CMD Slew Rate Training: 0=Disable, <b>1=Enable</b>.
+ UINT32 CMDDSEQ : 1; ///< - CMD Drive Strength and Tx Equalization: 0=Disable, <b>1=Enable</b>.
+ UINT32 CMDNORM : 1; ///< - CMD Normalization: 0=Disable, <b>1=Enable</b>.
+ UINT32 EWRDSEQ : 1; ///< - Early DQ Write Drive Strength and Equalization Training: 0=Disable, <b>1=Enable</b>.
+ UINT32 RsvdBits2 :28;
+} MEMORY_CONFIGURATION;
+
+/**
+ No CRC Memory Configuration
+ The contents of this structure are not CRC'd by the MRC for option change detection.\n
+ <b>Revision 1</b>:
+ - Initial version.
+
+ <b>Revision 2</b>:
+ - No changes (updated due to a change in MEMORY_CONFIGURATION)
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ SA_FUNCTION_CALLS SaCall; ///< Offset 28 - Function calls into the SA.
+ SA_MEMORY_FUNCTIONS MrcCall; ///< Offset 204 - Function calls into the MRC.
+ SPD_DATA_BUFFER *SpdData; ///< Offset 240 - Memory SPD data, will be used by the MRC when SPD SmBus address is zero.
+ SA_MEMORY_DQ_MAPPING *DqByteMap; ///< Offset 244 - LPDDR3 DQ byte mapping to CMD/CTL/CLK, from the CPU side.
+ SA_MEMORY_DQS_MAPPING *DqsMap; ///< Offset 248 - LPDDR3 DQS byte swizzling between CPU and DRAM.
+ SA_MEMORY_RCOMP *RcompData; ///< Offset 252 - DDR RCOMP resistors and target values.
+ /**
+ The minimum platform memory size required to pass control into DXE.
+ @note Some debug features, such as Intel Processor Trace and Intel Trace Hub,
+ may require updating this policy to a larger value to accommodate those memory requests.
+ @note 4GB restriction: Due to 32-bit memory address space restriction,
+ increasing this value above default is not guaranteed to work, and will depend on available memory in 4GB space.
+ **/
+ UINT64 PlatformMemorySize; ///< Offset 256
+ UINT32 MmaTestContentPtr; ///< Offset 264 - Pointer to MMA Test Content Data. Used in FSP.
+ UINT32 MmaTestContentSize; ///< Offset 268 - Size of MMA Test Content Data. Used in FSP.
+ UINT32 MmaTestConfigPtr; ///< Offset 272 - Pointer to MMA Test Config Data. Used in FSP.
+ UINT32 MmaTestConfigSize; ///< Offset 276 - Size of MMA Test Config Data. Used in FSP.
+ UINT32 CleanMemory:1; ///< Offset 280 - Ask MRC to clear memory content: <b>FALSE=Do not Clear Memory</b>; TRUE=Clear Memory
+ UINT32 RsvdBits0:31;
+ /**
+ Sets the serial debug message level\n
+ 0x00 = Disabled\n
+ 0x01 = Errors only\n
+ 0x02 = Errors and Warnings\n
+ <b>0x03 = Errors, Warnings, and Info</b>\n
+ 0x04 = Errors, Warnings, Info, and Events\n
+ 0x05 = Displays Memory Init Execution Time Summary only\n
+ **/
+ UINT8 SerialDebugLevel; ///< Offset 284
+ UINT8 Rsvd0[3]; ///< Offset 285
+} MEMORY_CONFIG_NO_CRC;
+#pragma pack(pop)
+
+#endif // _MEMORY_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MiscDxeConfig.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MiscDxeConfig.h
new file mode 100644
index 0000000000..18a5371c4b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/MiscDxeConfig.h
@@ -0,0 +1,35 @@
+/** @file
+ MISC DXE policy definitions
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MISC_DXE_CONFIG_H_
+#define _MISC_DXE_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#define MISC_DXE_CONFIG_REVISION 1
+
+/**
+ This data structure includes miscellaneous configuration variables such SA thermal device
+ control. The data elements should be initialized by a Platform Module.\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ UINT32 EnableAbove4GBMmio : 1; ///< Enable/disable above 4GB MMIO resource support: <b>0=Disable</b>, 1=Enable
+ UINT32 RsvdBits0 : 31; ///< Reserved bits.
+ EFI_PHYSICAL_ADDRESS *RmrrUsbBaseAddress; ///< The field is used to describe the platform USB Reserved memory for Intel VT-d support. Platform code should provide this information for Intel VT-d DXE driver use
+} MISC_DXE_CONFIG;
+#pragma pack(pop)
+
+#endif // _MISC_DXE_CONFIG_H_ \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
new file mode 100644
index 0000000000..0bf1934207
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
@@ -0,0 +1,38 @@
+/** @file
+ Policy details for miscellaneous configuration in System Agent
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_MISC_PEI_PREMEM_CONFIG_H_
+#define _SA_MISC_PEI_PREMEM_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#ifndef SA_MC_MAX_SOCKETS
+#define SA_MC_MAX_SOCKETS 4
+#endif
+
+#define SA_MISC_PEI_PREMEM_CONFIG_REVISION 1
+
+/**
+ This configuration block is to configure SA Miscellaneous variables during PEI Pre-Mem phase like programming
+ different System Agent BARs, TsegSize, IedSize, MmioSize required etc.
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ UINT8 SpdAddressTable[SA_MC_MAX_SOCKETS];///< Offset 28 Memory DIMMs' SPD address for reading SPD data. <b>example: SpdAddressTable[0]=0xA2(C0D0), SpdAddressTable[1]=0xA0(C0D1), SpdAddressTable[2]=0xA2(C1D0), SpdAddressTable[3]=0xA0(C1D1)</b>
+ UINT32 MchBar; ///< Offset 36 Address of System Agent MCHBAR: <b>0xFED10000</b>
+} SA_MISC_PEI_PREMEM_CONFIG;
+#pragma pack(pop)
+
+#endif // _SA_MISC_PEI_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/VtdConfig.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/VtdConfig.h
new file mode 100644
index 0000000000..086d70849a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/ConfigBlock/VtdConfig.h
@@ -0,0 +1,46 @@
+/** @file
+ VT-d policy definitions.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _VTD_CONFIG_H_
+#define _VTD_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#define SA_VTD_ENGINE_NUMBER 2
+
+#define VTD_CONFIG_REVISION 1
+
+/**
+ The data elements should be initialized by a Platform Module.
+ The data structure is for VT-d driver initialization\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ /**
+ Offset 28:0 :
+ VT-D Support can be verified by reading CAP ID register as expalined in BIOS Spec.
+ This policy is for debug purpose only.
+ If VT-D is not supported, all other policies in this config block will be ignored.
+ <b>0 = To use Vt-d</b>;
+ 1 = Avoids programming Vtd bars, Vtd overrides and DMAR table.
+ **/
+ UINT32 VtdDisable : 1;
+ UINT32 X2ApicOptOut : 1; ///< Offset 28:1 :This field is used to enable the X2APIC_OPT_OUT bit in the DMAR table. 1=Enable/Set and <b>0=Disable/Clear</b>
+ UINT32 RsvdBits0 : 30; ///< Offset 28:2 :Reserved bits for future use
+ UINT32 BaseAddress[SA_VTD_ENGINE_NUMBER]; ///< Offset 32: This field is used to describe the base addresses for VT-d function: <b>BaseAddress[0]=0xFED90000, BaseAddress[0]=0xFED91000 </b>
+} VTD_CONFIG;
+#pragma pack(pop)
+
+#endif // _VTD_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/DmaRemappingTable.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/DmaRemappingTable.h
new file mode 100644
index 0000000000..0c49f98f2c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/DmaRemappingTable.h
@@ -0,0 +1,112 @@
+/** @file
+ This code defines ACPI DMA Remapping table related definitions.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _DMA_REMAPPING_TABLE_H_
+#define _DMA_REMAPPING_TABLE_H_
+
+#include <Uefi.h>
+#include <Base.h>
+#include <IndustryStandard/Acpi30.h>
+
+#pragma pack(1)
+///
+/// DMAR table signature
+///
+#define EFI_ACPI_VTD_DMAR_TABLE_SIGNATURE 0x52414D44 ///< "DMAR"
+#define EFI_ACPI_DMAR_TABLE_REVISION 1
+#define EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH 0x10
+#define EFI_ACPI_RMRR_HEADER_LENGTH 0x18
+#define MAX_PCI_DEPTH 5
+
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+ UINT16 Reserved;
+ UINT8 EnumId;
+ UINT8 StartBusNumber;
+ UINT8 PciPath[2]; // device, function
+} EFI_ACPI_DEV_SCOPE_STRUCTURE;
+
+typedef struct {
+ UINT16 Type;
+ UINT16 Length;
+ UINT8 Flags;
+ UINT8 Reserved;
+ UINT16 SegmentNum;
+ EFI_PHYSICAL_ADDRESS RegisterBaseAddress;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[1];
+} EFI_ACPI_DRHD_ENGINE1_STRUCT;
+
+typedef struct {
+ UINT16 Type;
+ UINT16 Length;
+ UINT8 Flags;
+ UINT8 Reserved;
+ UINT16 SegmentNum;
+ EFI_PHYSICAL_ADDRESS RegisterBaseAddress;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[14];
+} EFI_ACPI_DRHD_ENGINE2_STRUCT;
+
+typedef struct {
+ UINT16 Type;
+ UINT16 Length;
+ UINT16 Reserved;
+ UINT16 SegmentNum;
+ EFI_PHYSICAL_ADDRESS RmrBaseAddress;
+ EFI_PHYSICAL_ADDRESS RmrLimitAddress;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[2];
+} EFI_ACPI_RMRR_USB_STRUC;
+
+typedef struct {
+ UINT16 Type;
+ UINT16 Length;
+ UINT16 Reserved;
+ UINT16 SegmentNum;
+ EFI_PHYSICAL_ADDRESS RmrBaseAddress;
+ EFI_PHYSICAL_ADDRESS RmrLimitAddress;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[1]; // IGD
+} EFI_ACPI_RMRR_IGD_STRUC;
+
+typedef struct {
+ UINT16 Type;
+ UINT16 Length;
+ UINT8 Reserved[3];
+ UINT8 AcpiDeviceNumber;
+ UINT8 AcpiObjectName[20];
+} EFI_ACPI_ANDD_STRUC;
+
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT8 HostAddressWidth;
+ UINT8 Flags;
+ UINT8 Reserved[10];
+ EFI_ACPI_DRHD_ENGINE1_STRUCT DrhdEngine1;
+ EFI_ACPI_DRHD_ENGINE2_STRUCT DrhdEngine2;
+ EFI_ACPI_RMRR_USB_STRUC RmrrUsb;
+ EFI_ACPI_RMRR_IGD_STRUC RmrrIgd;
+ EFI_ACPI_ANDD_STRUC AnddI2C0;
+ EFI_ACPI_ANDD_STRUC AnddI2C1;
+ EFI_ACPI_ANDD_STRUC AnddI2C2;
+ EFI_ACPI_ANDD_STRUC AnddI2C3;
+ EFI_ACPI_ANDD_STRUC AnddI2C4;
+ EFI_ACPI_ANDD_STRUC AnddI2C5;
+ EFI_ACPI_ANDD_STRUC AnddSpi0;
+ EFI_ACPI_ANDD_STRUC AnddSpi1;
+ EFI_ACPI_ANDD_STRUC AnddUa00;
+ EFI_ACPI_ANDD_STRUC AnddUa01;
+ EFI_ACPI_ANDD_STRUC AnddUa02;
+} EFI_ACPI_DMAR_TABLE;
+
+#pragma pack()
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h
new file mode 100644
index 0000000000..12274d797d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h
@@ -0,0 +1,65 @@
+/** @file
+ Prototype of the DxeSaPolicyLib library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _DXE_SA_POLICY_LIB_H_
+#define _DXE_SA_POLICY_LIB_H_
+
+#include <Protocol/SaPolicy.h>
+
+/**
+ This function prints the DXE phase policy.
+
+ @param[in] SaPolicy - SA DXE Policy protocol
+**/
+VOID
+SaPrintPolicyProtocol (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+;
+
+/**
+ CreateSaDxeConfigBlocks generates the config blocksg of SA DXE Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SaPolicy The pointer to get SA Policy Protocol instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreateSaDxeConfigBlocks(
+ IN OUT SA_POLICY_PROTOCOL **SaPolicy
+);
+
+/**
+ SaInstallPolicyProtocol installs SA Policy.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SaPolicy The pointer to SA Policy Protocol instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+SaInstallPolicyProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+;
+
+#endif // _DXE_SA_POLICY_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h
new file mode 100644
index 0000000000..6348fd003e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h
@@ -0,0 +1,91 @@
+/** @file
+ Prototype of the PeiSaPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_SA_POLICY_LIB_H_
+#define _PEI_SA_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+#include <Library/ConfigBlockLib.h>
+
+/**
+ This function prints the PEI phase PreMem policy.
+
+ @param[in] SiPolicyPreMemPpi The RC PreMem Policy PPI instance
+**/
+VOID
+EFIAPI
+SaPrintPolicyPpiPreMem (
+ IN SI_PREMEM_POLICY_PPI *SiPolicyPreMemPpi
+ );
+
+/**
+ This function prints the PEI phase policy.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+SaPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ Get SA config block table total size.
+
+ @retval Size of SA config block table
+**/
+UINT16
+EFIAPI
+SaGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ Get SA config block table total size.
+
+ @retval Size of SA config block table
+**/
+UINT16
+EFIAPI
+SaGetConfigBlockTotalSizePreMem (
+ VOID
+ );
+
+/**
+ SaAddConfigBlocksPreMem add all SA config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add SA config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SaAddConfigBlocksPreMem (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+/**
+ SaAddConfigBlocks add all SA config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add SA config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SaAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ );
+#endif // _PEI_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h
new file mode 100644
index 0000000000..f3762e91a5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h
@@ -0,0 +1,34 @@
+/** @file
+ Header file for SaPlatformLib.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SA_PLATFORM_LIB_H_
+#define _SA_PLATFORM_LIB_H_
+
+#include <SaAccess.h>
+#include <CpuAccess.h>
+
+/**
+ Determine if PCH Link is DMI/OPI
+
+ @param[in] CpuModel CPU model
+
+ @retval TRUE DMI
+ @retval FALSE OPI
+**/
+BOOLEAN
+IsPchLinkDmi (
+ IN CPU_FAMILY CpuModel
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/MemInfoHob.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
new file mode 100644
index 0000000000..dbf93ac265
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
@@ -0,0 +1,244 @@
+/** @file
+ This file contains definitions required for creation of
+ Memory S3 Save data, Memory Info data and Memory Platform
+ data hobs.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MEM_INFO_HOB_H_
+#define _MEM_INFO_HOB_H_
+
+#pragma pack (push, 1)
+
+extern EFI_GUID gSiMemoryS3DataGuid;
+extern EFI_GUID gSiMemoryInfoDataGuid;
+extern EFI_GUID gSiMemoryPlatformDataGuid;
+
+#define MAX_NODE 1
+#define MAX_CH 2
+#define MAX_DIMM 2
+
+///
+/// Host reset states from MRC.
+///
+#define WARM_BOOT 2
+
+#define R_MC_CHNL_RANK_PRESENT 0x7C
+#define B_RANK0_PRS BIT0
+#define B_RANK1_PRS BIT1
+#define B_RANK2_PRS BIT4
+#define B_RANK3_PRS BIT5
+
+// @todo remove and use the MdePkg\Include\Pi\PiHob.h
+#if !defined(_PEI_HOB_H_) && !defined(__PI_HOB_H__)
+#ifndef __HOB__H__
+typedef struct _EFI_HOB_GENERIC_HEADER {
+ UINT16 HobType;
+ UINT16 HobLength;
+ UINT32 Reserved;
+} EFI_HOB_GENERIC_HEADER;
+
+typedef struct _EFI_HOB_GUID_TYPE {
+ EFI_HOB_GENERIC_HEADER Header;
+ EFI_GUID Name;
+ ///
+ /// Guid specific data goes here
+ ///
+} EFI_HOB_GUID_TYPE;
+#endif
+#endif
+
+///
+/// Defines taken from MRC so avoid having to include MrcInterface.h
+///
+
+//
+// Matches MAX_SPD_SAVE define in MRC
+//
+#ifndef MAX_SPD_SAVE
+#define MAX_SPD_SAVE 29
+#endif
+
+//
+// MRC version description.
+//
+typedef struct {
+ UINT8 Major; ///< Major version number
+ UINT8 Minor; ///< Minor version number
+ UINT8 Rev; ///< Revision number
+ UINT8 Build; ///< Build number
+} SiMrcVersion;
+
+//
+// Matches MrcDimmSts enum in MRC
+//
+#ifndef DIMM_ENABLED
+#define DIMM_ENABLED 0 // DIMM/rank Pair is enabled, presence will be detected.
+#endif
+#ifndef DIMM_DISABLED
+#define DIMM_DISABLED 1 // DIMM/rank Pair is disabled, regardless of presence.
+#endif
+#ifndef DIMM_PRESENT
+#define DIMM_PRESENT 2 // There is a DIMM present in the slot/rank pair and it will be used.
+#endif
+#ifndef DIMM_NOT_PRESENT
+#define DIMM_NOT_PRESENT 3 // There is no DIMM present in the slot/rank pair.
+#endif
+
+//
+// Matches MrcBootMode enum in MRC
+//
+#ifndef bmCold
+#define bmCold 0 // Cold boot
+#endif
+#ifndef bmWarm
+#define bmWarm 1 // Warm boot
+#endif
+#ifndef bmS3
+#define bmS3 2 // S3 resume
+#endif
+#ifndef bmFast
+#define bmFast 3 // Fast boot
+#endif
+
+//
+// Matches MrcDdrType enum in MRC
+//
+#ifndef MRC_DDR_TYPE_DDR4
+#define MRC_DDR_TYPE_DDR4 0
+#endif
+#ifndef MRC_DDR_TYPE_DDR3
+#define MRC_DDR_TYPE_DDR3 1
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR3
+#define MRC_DDR_TYPE_LPDDR3 2
+#endif
+#ifndef MRC_DDR_TYPE_UNKNOWN
+#define MRC_DDR_TYPE_UNKNOWN 3
+#endif
+
+#define MAX_PROFILE_NUM 4 // number of memory profiles supported
+#define MAX_XMP_PROFILE_NUM 2 // number of XMP profiles supported
+
+//
+// DIMM timings
+//
+typedef struct {
+ UINT32 tCK; ///< Memory cycle time, in femtoseconds.
+ UINT16 NMode; ///< Number of tCK cycles for the channel DIMM's command rate mode.
+ UINT16 tCL; ///< Number of tCK cycles for the channel DIMM's CAS latency.
+ UINT16 tCWL; ///< Number of tCK cycles for the channel DIMM's minimum CAS write latency time.
+ UINT16 tFAW; ///< Number of tCK cycles for the channel DIMM's minimum four activate window delay time.
+ UINT16 tRAS; ///< Number of tCK cycles for the channel DIMM's minimum active to precharge delay time.
+ UINT16 tRCDtRP; ///< Number of tCK cycles for the channel DIMM's minimum RAS# to CAS# delay time and Row Precharge delay time.
+ UINT16 tREFI; ///< Number of tCK cycles for the channel DIMM's minimum Average Periodic Refresh Interval.
+ UINT16 tRFC; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRFC2; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRFC4; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRPab; ///< Number of tCK cycles for the channel DIMM's minimum row precharge delay time for all banks.
+ UINT16 tRRD; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time.
+ UINT16 tRRD_L; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for same bank groups.
+ UINT16 tRRD_S; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for different bank groups.
+ UINT16 tRTP; ///< Number of tCK cycles for the channel DIMM's minimum internal read to precharge command delay time.
+ UINT16 tWR; ///< Number of tCK cycles for the channel DIMM's minimum write recovery time.
+ UINT16 tWTR; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time.
+ UINT16 tWTR_L; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for same bank groups.
+ UINT16 tWTR_S; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for different bank groups.
+} MRC_CH_TIMING;
+
+///
+/// Memory SMBIOS & OC Memory Data Hob
+///
+typedef struct {
+ UINT8 Status; ///< See MrcDimmStatus for the definition of this field.
+ UINT8 DimmId;
+ UINT32 DimmCapacity; ///< DIMM size in MBytes.
+ UINT16 MfgId;
+ UINT8 ModulePartNum[20]; ///< Module part number for DDR3 is 18 bytes however for DRR4 20 bytes as per JEDEC Spec, so reserving 20 bytes
+ UINT8 RankInDimm; ///< The number of ranks in this DIMM.
+ UINT8 SpdDramDeviceType; ///< Save SPD DramDeviceType information needed for SMBIOS structure creation.
+ UINT8 SpdModuleType; ///< Save SPD ModuleType information needed for SMBIOS structure creation.
+ UINT8 SpdModuleMemoryBusWidth; ///< Save SPD ModuleMemoryBusWidth information needed for SMBIOS structure creation.
+ UINT8 SpdSave[MAX_SPD_SAVE]; ///< Save SPD Manufacturing information needed for SMBIOS structure creation.
+} DIMM_INFO;
+
+typedef struct {
+ UINT8 Status; ///< Indicates whether this channel should be used.
+ UINT8 ChannelId;
+ UINT8 DimmCount; ///< Number of valid DIMMs that exist in the channel.
+ MRC_CH_TIMING Timing[MAX_PROFILE_NUM]; ///< The channel timing values.
+ DIMM_INFO Dimm[MAX_DIMM]; ///< Save the DIMM output characteristics.
+} CHANNEL_INFO;
+
+typedef struct {
+ UINT8 Status; ///< Indicates whether this controller should be used.
+ UINT16 DeviceId; ///< The PCI device id of this memory controller.
+ UINT8 RevisionId; ///< The PCI revision id of this memory controller.
+ UINT8 ChannelCount; ///< Number of valid channels that exist on the controller.
+ CHANNEL_INFO Channel[MAX_CH]; ///< The following are channel level definitions.
+} CONTROLLER_INFO;
+
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType;
+ UINT8 Revision;
+ UINT16 DataWidth;
+ /** As defined in SMBIOS 3.0 spec
+ Section 7.18.2 and Table 75
+ **/
+ UINT8 DdrType; ///< DDR type: DDR3, DDR4, or LPDDR3
+ UINT32 Frequency; ///< The system's common memory controller frequency in MT/s.
+ /** As defined in SMBIOS 3.0 spec
+ Section 7.17.3 and Table 72
+ **/
+ UINT8 ErrorCorrectionType;
+
+ SiMrcVersion Version;
+ UINT32 FreqMax;
+ BOOLEAN EccSupport;
+ UINT8 MemoryProfile;
+ UINT32 TotalPhysicalMemorySize;
+ UINT32 DefaultXmptCK[MAX_XMP_PROFILE_NUM]; // Stores the tCK value read from SPD XMP profiles if they exist.
+ UINT8 XmpProfileEnable; // If XMP capable DIMMs are detected, this will indicate which XMP Profiles are common among all DIMMs.
+ UINT8 Ratio;
+ UINT8 RefClk;
+ UINT32 VddVoltage[MAX_PROFILE_NUM];
+ CONTROLLER_INFO Controller[MAX_NODE];
+} MEMORY_INFO_DATA_HOB;
+
+/**
+ Memory Platform Data Hob
+
+ <b>Revision 1:</b>
+ - Initial version.
+ <b>Revision 2:</b>
+ - Added TsegBase, PrmrrSize, PrmrrBase, Gttbase, MmioSize, PciEBaseAddress fields
+**/
+typedef struct {
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ UINT32 BootMode;
+ UINT32 TsegSize;
+ UINT32 TsegBase;
+ UINT32 PrmrrSize;
+ UINT32 PrmrrBase;
+ UINT32 GttBase;
+ UINT32 MmioSize;
+ UINT32 PciEBaseAddress;
+} MEMORY_PLATFORM_DATA;
+
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType;
+ MEMORY_PLATFORM_DATA Data;
+ UINT8 *Buffer;
+} MEMORY_PLATFORM_DATA_HOB;
+#pragma pack (pop)
+
+#endif // _MEM_INFO_HOB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/GopPolicy.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/GopPolicy.h
new file mode 100644
index 0000000000..e7e72e5e53
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/GopPolicy.h
@@ -0,0 +1,78 @@
+/** @file
+ Interface definition for GopPolicy Protocol.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GOP_POLICY_PROTOCOL_H_
+#define _GOP_POLICY_PROTOCOL_H_
+
+
+#define GOP_POLICY_PROTOCOL_REVISION_01 0x01
+#define GOP_POLICY_PROTOCOL_REVISION_03 0x03
+
+typedef enum {
+ LidClosed,
+ LidOpen,
+ LidStatusMax
+} LID_STATUS;
+
+typedef enum {
+ Docked,
+ UnDocked,
+ DockStatusMax
+} DOCK_STATUS;
+
+///
+/// Function to retrieve LID status
+///
+typedef
+EFI_STATUS
+(EFIAPI *GET_PLATFORM_LID_STATUS) (
+ OUT LID_STATUS * CurrentLidStatus
+ );
+
+///
+/// Function to retrieve Dock status
+///
+typedef
+EFI_STATUS
+(EFIAPI *GET_PLATFORM_DOCK_STATUS) (
+ OUT DOCK_STATUS CurrentDockStatus
+);
+
+///
+/// Function to retrieve VBT table address and size
+///
+typedef
+EFI_STATUS
+(EFIAPI *GET_VBT_DATA) (
+ OUT EFI_PHYSICAL_ADDRESS * VbtAddress,
+ OUT UINT32 *VbtSize
+ );
+
+/**
+ System Agent Graphics Output Protocol (GOP) - Policy Protocol\n
+ Graphics Output Protocol (GOP) is a UEFI API replacing legacy Video ROMs for EFI boot\n
+ When GOP Driver is used this protocol can be consumed by GOP driver or platform code for GOP relevant initialization\n
+ All functions in this protocol should be initialized by platform code basing on platform implementation\n
+**/
+typedef struct {
+ UINT32 Revision; ///< Protocol revision
+ GET_PLATFORM_LID_STATUS GetPlatformLidStatus; ///< Protocol function to get Lid Status. Platform code should provide this function basing on design.
+ GET_VBT_DATA GetVbtData; ///< Protocol function to get Vbt Data address and size. Platform code should provide this function basing on design.
+ GET_PLATFORM_DOCK_STATUS GetPlatformDockStatus; ///< Function pointer for get platform dock status.
+ EFI_GUID GopOverrideGuid; ///< A GUID provided by BIOS in case GOP is to be overridden.
+} GOP_POLICY_PROTOCOL;
+
+extern EFI_GUID gGopPolicyProtocolGuid;
+extern EFI_GUID gIntelGraphicsVbtGuid;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/IgdOpRegion.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/IgdOpRegion.h
new file mode 100644
index 0000000000..b39ccc31d4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/IgdOpRegion.h
@@ -0,0 +1,170 @@
+/** @file
+ This file is part of the IGD OpRegion Implementation. The IGD OpRegion is
+ an interface between system BIOS, ASL code, and Graphics drivers.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+@par Specification Reference:
+ - IGD OpRegion/Software SCI SPEC
+**/
+#ifndef _IGD_OPREGION_PROTOCOL_H_
+#define _IGD_OPREGION_PROTOCOL_H_
+
+extern EFI_GUID gIgdOpRegionProtocolGuid;
+
+/**
+ Protocol data definitions
+
+
+ OpRegion structures:
+ Sub-structures define the different parts of the OpRegion followed by the
+ main structure representing the entire OpRegion.
+
+ Note: These structures are packed to 1 byte offsets because the exact
+ data location is requred by the supporting design specification due to
+ the fact that the data is used by ASL and Graphics driver code compiled
+ separatly.
+**/
+#pragma pack(1)
+///
+/// OpRegion header (mailbox 0) structure and defines.
+///
+typedef struct {
+ CHAR8 SIGN[0x10]; ///< Offset 0 OpRegion signature
+ UINT32 SIZE; ///< Offset 16 OpRegion size
+ UINT32 OVER; ///< Offset 20 OpRegion structure version
+ UINT8 SVER[0x20]; ///< Offset 24 System BIOS build version
+ UINT8 VVER[0x10]; ///< Offset 56 Video BIOS build version
+ UINT8 GVER[0x10]; ///< Offset 72 Graphic driver build version
+ UINT32 MBOX; ///< Offset 88 Mailboxes supported
+ UINT32 DMOD; ///< Offset 92 Driver Model
+ UINT32 PCON; ///< Offset 96 Platform Capabilities
+ CHAR16 DVER[0x10]; ///< Offset 100 GOP Version
+ UINT8 RHD1[0x7C]; ///< Offset 132 Reserved
+} OPREGION_HEADER;
+#pragma pack()
+#pragma pack(1)
+///
+/// OpRegion mailbox 1 (public ACPI Methods).
+///
+typedef struct {
+ UINT32 DRDY; ///< Offset 0 Driver readiness
+ UINT32 CSTS; ///< Offset 4 Status
+ UINT32 CEVT; ///< Offset 8 Current event
+ UINT8 RM11[0x14]; ///< Offset 12 Reserved
+ UINT32 DIDL; ///< Offset 32 Supported display device 1
+ UINT32 DDL2; ///< Offset 36 Supported display device 2
+ UINT32 DDL3; ///< Offset 40 Supported display device 3
+ UINT32 DDL4; ///< Offset 44 Supported display device 4
+ UINT32 DDL5; ///< Offset 48 Supported display device 5
+ UINT32 DDL6; ///< Offset 52 Supported display device 6
+ UINT32 DDL7; ///< Offset 56 Supported display device 7
+ UINT32 DDL8; ///< Offset 60 Supported display device 8
+ UINT32 CPDL; ///< Offset 64 Currently present display device 1
+ UINT32 CPL2; ///< Offset 68 Currently present display device 2
+ UINT32 CPL3; ///< Offset 72 Currently present display device 3
+ UINT32 CPL4; ///< Offset 76 Currently present display device 4
+ UINT32 CPL5; ///< Offset 80 Currently present display device 5
+ UINT32 CPL6; ///< Offset 84 Currently present display device 6
+ UINT32 CPL7; ///< Offset 88 Currently present display device 7
+ UINT32 CPL8; ///< Offset 92 Currently present display device 8
+ UINT32 CADL; ///< Offset 96 Currently active display device 1
+ UINT32 CAL2; ///< Offset 100 Currently active display device 2
+ UINT32 CAL3; ///< Offset 104 Currently active display device 3
+ UINT32 CAL4; ///< Offset 108 Currently active display device 4
+ UINT32 CAL5; ///< Offset 112 Currently active display device 5
+ UINT32 CAL6; ///< Offset 116 Currently active display device 6
+ UINT32 CAL7; ///< Offset 120 Currently active display device 7
+ UINT32 CAL8; ///< Offset 124 Currently active display device 8
+ UINT32 NADL; ///< Offset 128 Next active device 1
+ UINT32 NDL2; ///< Offset 132 Next active device 2
+ UINT32 NDL3; ///< Offset 136 Next active device 3
+ UINT32 NDL4; ///< Offset 140 Next active device 4
+ UINT32 NDL5; ///< Offset 144 Next active device 5
+ UINT32 NDL6; ///< Offset 148 Next active device 6
+ UINT32 NDL7; ///< Offset 152 Next active device 7
+ UINT32 NDL8; ///< Offset 156 Next active device 8
+ UINT32 ASLP; ///< Offset 160 ASL sleep timeout
+ UINT32 TIDX; ///< Offset 164 Toggle table index
+ UINT32 CHPD; ///< Offset 168 Current hot plug enable indicator
+ UINT32 CLID; ///< Offset 172 Current lid state indicator
+ UINT32 CDCK; ///< Offset 176 Current docking state indicator
+ UINT32 SXSW; ///< Offset 180 Display Switch notification on Sx State resume
+ UINT32 EVTS; ///< Offset 184 Events supported by ASL
+ UINT32 CNOT; ///< Offset 188 Current OS Notification
+ UINT32 NRDY; ///< Offset 192 Reasons for DRDY = 0
+ UINT8 RM12[0x3C]; ///< Offset 196 Reserved
+} OPREGION_MBOX1;
+#pragma pack()
+#pragma pack(1)
+///
+/// OpRegion mailbox 2 (Software SCI Interface).
+///
+typedef struct {
+ UINT32 SCIC; ///< Offset 0 Software SCI function number parameters
+ UINT32 PARM; ///< Offset 4 Software SCI additional parameters
+ UINT32 DSLP; ///< Offset 8 Driver sleep timeout
+ UINT8 RM21[0xF4]; ///< Offset 12 Reserved
+} OPREGION_MBOX2;
+#pragma pack()
+#pragma pack(1)
+///
+/// OpRegion mailbox 3 (Power Conservation).
+///
+typedef struct {
+ UINT32 ARDY; ///< Offset 0 Driver readiness
+ UINT32 ASLC; ///< Offset 4 ASLE interrupt command / status
+ UINT32 TCHE; ///< Offset 8 Technology enabled indicator
+ UINT32 ALSI; ///< Offset 12 Current ALS illuminance reading
+ UINT32 BCLP; ///< Offset 16 Backlight britness to set
+ UINT32 PFIT; ///< Offset 20 Panel fitting Request
+ UINT32 CBLV; ///< Offset 24 Brightness Current State
+ UINT16 BCLM[0x14]; ///< Offset 28 Backlight Brightness Level Duty Cycle Mapping Table
+ UINT32 CPFM; ///< Offset 68 Panel Fitting Current Mode
+ UINT32 EPFM; ///< Offset 72 Enabled Panel Fitting Modes
+ UINT8 PLUT[0x4A]; ///< Offset 76 Panel Look Up Table
+ UINT32 PFMB; ///< Offset 150 PWM Frequency and Minimum Brightness
+ UINT32 CCDV; ///< Offset 154 Color Correction Default Values
+ UINT32 PCFT; ///< Offset 158 Power Conservation Features
+ UINT32 SROT; ///< Offset 162 Supported Rotation angle
+ UINT32 IUER; ///< Offset 166 Intel Ultrabook Event Register
+ UINT64 FDSP; ///< Offset 170 FFS Display Physical address
+ UINT32 FDSS; ///< Offset 178 FFS Display Size
+ UINT8 RM32[0x4A]; ///< Offset 182 Reserved
+} OPREGION_MBOX3;
+#pragma pack()
+#pragma pack(1)
+///
+/// OpRegion mailbox 4 (VBT).
+///
+typedef struct {
+ UINT8 GVD1[0x1C00]; ///< Reserved
+} OPREGION_VBT;
+#pragma pack()
+#pragma pack(1)
+///
+/// IGD OpRegion Structure
+///
+typedef struct {
+ OPREGION_HEADER Header; ///< OpRegion header
+ OPREGION_MBOX1 MBox1; ///< Mailbox 1: Public ACPI Methods
+ OPREGION_MBOX2 MBox2; ///< Mailbox 2: Software SCI Inteface
+ OPREGION_MBOX3 MBox3; ///< Mailbox 3: Power Conservation
+ OPREGION_VBT VBT; ///< VBT: Video BIOS Table (OEM customizable data)
+} IGD_OPREGION_STRUC;
+#pragma pack()
+///
+/// IGD OpRegion Protocol
+///
+typedef struct {
+ IGD_OPREGION_STRUC *OpRegion; ///< IGD Operation Region Structure
+} IGD_OPREGION_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/MemInfo.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/MemInfo.h
new file mode 100644
index 0000000000..ceadd739d6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/MemInfo.h
@@ -0,0 +1,122 @@
+/** @file
+ This protocol provides the memory information data, such as
+ total physical memory size, memory frequency, memory size
+ of each dimm and rank.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MEM_INFO_PROTOCOL_H_
+#define _MEM_INFO_PROTOCOL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gMemInfoProtocolGuid;
+
+//
+// Protocol definitions
+//
+#define NODE_NUM 1
+#define CH_NUM 2
+#define DIMM_NUM 2
+#define RANK_NUM 2
+#define SLOT_NUM (CH_NUM * DIMM_NUM)
+#define PROFILE_NUM 4 // number of memory profiles supported
+#define XMP_PROFILE_NUM 2 // number of XMP profiles supported
+
+//
+// Matches MrcDdrType enum in MRC
+//
+#ifndef MRC_DDR_TYPE_DDR4
+#define MRC_DDR_TYPE_DDR4 0
+#endif
+#ifndef MRC_DDR_TYPE_DDR3
+#define MRC_DDR_TYPE_DDR3 1
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR3
+#define MRC_DDR_TYPE_LPDDR3 2
+#endif
+#ifndef MRC_DDR_TYPE_UNKNOWN
+#define MRC_DDR_TYPE_UNKNOWN 3
+#endif
+
+//
+// Matches MrcDimmSts enum in MRC
+//
+#ifndef DIMM_ENABLED
+#define DIMM_ENABLED 0 // DIMM/rank Pair is enabled, presence will be detected.
+#endif
+#ifndef DIMM_DISABLED
+#define DIMM_DISABLED 1 // DIMM/rank Pair is disabled, regardless of presence.
+#endif
+#ifndef DIMM_PRESENT
+#define DIMM_PRESENT 2 // There is a DIMM present in the slot/rank pair and it will be used.
+#endif
+#ifndef DIMM_NOT_PRESENT
+#define DIMM_NOT_PRESENT 3 // There is no DIMM present in the slot/rank pair.
+#endif
+
+#pragma pack(1)
+///
+/// Memory timing Structure
+///
+typedef struct {
+ UINT32 tCK; ///< Offset 0 Memory cycle time, in femtoseconds.
+ UINT16 NMode; ///< Offset 4 Number of tCK cycles for the channel DIMM's command rate mode.
+ UINT16 tCL; ///< Offset 6 Number of tCK cycles for the channel DIMM's CAS latency.
+ UINT16 tCWL; ///< Offset 8 Number of tCK cycles for the channel DIMM's minimum CAS write latency time.
+ UINT16 tFAW; ///< Offset 10 Number of tCK cycles for the channel DIMM's minimum four activate window delay time.
+ UINT16 tRAS; ///< Offset 12 Number of tCK cycles for the channel DIMM's minimum active to precharge delay time.
+ UINT16 tRCDtRP; ///< Offset 14 Number of tCK cycles for the channel DIMM's minimum RAS# to CAS# delay time and Row Precharge delay time
+ UINT16 tREFI; ///< Offset 16 Number of tCK cycles for the channel DIMM's minimum Average Periodic Refresh Interval.
+ UINT16 tRFC; ///< Offset 18 Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRPab; ///< Offset 20 Number of tCK cycles for the channel DIMM's minimum row precharge delay time for all banks.
+ UINT16 tRRD; ///< Offset 22 Number of tCK cycles for the channel DIMM's minimum row active to row active delay time.
+ UINT16 tRTP; ///< Offset 24 Number of tCK cycles for the channel DIMM's minimum internal read to precharge command delay time.
+ UINT16 tWR; ///< Offset 26 Number of tCK cycles for the channel DIMM's minimum write recovery time.
+ UINT16 tWTR; ///< Offset 28 Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time.
+ UINT8 Rsvd[2]; ///< Offset 30
+} MEMORY_TIMING;
+
+// @todo use the MemInfoHob data instead of duplicate structure.
+///
+/// Memory information Data Structure
+///
+typedef struct {
+ MEMORY_TIMING Timing[PROFILE_NUM]; ///< Offset 0 Timming information for the DIMM
+ UINT32 memSize; ///< Offset 128 Total physical memory size
+ UINT16 ddrFreq; ///< Offset 132 DDR Current Frequency
+ UINT16 ddrFreqMax; ///< Offset 134 DDR Maximum Frequency
+ UINT16 dimmSize[NODE_NUM * CH_NUM * DIMM_NUM]; ///< Offset 136 Size of each DIMM
+ UINT16 VddVoltage[PROFILE_NUM]; ///< Offset 144 The voltage setting for the DIMM
+ UINT8 DimmStatus[NODE_NUM * CH_NUM * DIMM_NUM]; ///< Offset 152 The enumeration value from MrcDimmSts
+ UINT8 RankInDimm[NODE_NUM * CH_NUM * DIMM_NUM]; ///< Offset 156 Number of ranks in a DIMM
+ UINT8 *DimmsSpdData[NODE_NUM * CH_NUM * DIMM_NUM]; ///< Offset 160 SPD data of each DIMM
+ UINT8 RefClk; ///< Offset 192 Reference Clock
+ UINT8 Ratio; ///< Offset 193 Clock Multiplier
+ BOOLEAN EccSupport; ///< Offset 194 ECC supported or not
+ UINT8 Profile; ///< Offset 195 Currently running memory profile
+ UINT8 XmpProfileEnable; ///< Offset 196 If XMP capable DIMMs are detected, this will indicate which XMP Profiles are common among all DIMMs.
+ UINT8 DdrType; ///< Offset 197 Current DDR type, see DDR_TYPE_xxx defines above
+ UINT8 Reserved[2]; ///< Offset 198 Reserved bytes for future use
+ UINT32 DefaultXmptCK[XMP_PROFILE_NUM]; ///< Offset 200 The Default XMP tCK values read from SPD.
+} MEMORY_INFO_DATA;
+#pragma pack()
+
+///
+/// Memory information Protocol definition
+///
+typedef struct {
+ MEMORY_INFO_DATA MemInfoData; ///< Memory Information Data Structure
+} MEM_INFO_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaGlobalNvsArea.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaGlobalNvsArea.h
new file mode 100644
index 0000000000..5daf183c1a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaGlobalNvsArea.h
@@ -0,0 +1,32 @@
+/** @file
+ Definition of the System Agent global NVS area protocol.
+ This protocol publishes the address and format of a global ACPI NVS buffer
+ used as a communications buffer between SMM/DXE/PEI code and ASL code.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SYSTEM_AGENT_GLOBAL_NVS_AREA_H_
+#define _SYSTEM_AGENT_GLOBAL_NVS_AREA_H_
+
+#include "SaNvs.h"
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gSaGlobalNvsAreaProtocolGuid;
+
+///
+/// System Agent Global NVS Area Protocol
+///
+typedef struct {
+ SYSTEM_AGENT_GLOBAL_NVS_AREA *Area; ///< System Agent Global NVS Area Structure
+} SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaNvs.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaNvs.h
new file mode 100644
index 0000000000..8f6ec57304
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaNvs.h
@@ -0,0 +1,138 @@
+/**@file
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+ //
+ // Define SA NVS Area operatino region.
+ //
+
+#ifndef _SA_NVS_H_
+#define _SA_NVS_H_
+
+#pragma pack (push,1)
+typedef struct {
+ UINT32 IgdOpRegionAddress; ///< Offset 0 IGD OpRegion base address
+ UINT8 GfxTurboIMON; ///< Offset 4 IMON Current Value
+ UINT8 IgdState; ///< Offset 5 IGD State (Primary Display = 1)
+ UINT8 IgdBootType; ///< Offset 6 IGD Boot Display Device
+ UINT8 IgdPanelType; ///< Offset 7 IGD Panel Type CMOS option
+ UINT8 IgdPanelScaling; ///< Offset 8 IGD Panel Scaling
+ UINT8 IgdBiaConfig; ///< Offset 9 IGD BIA Configuration
+ UINT8 IgdSscConfig; ///< Offset 10 IGD SSC Configuration
+ UINT8 IgdDvmtMemSize; ///< Offset 11 IGD DVMT Memory Size
+ UINT8 IgdFunc1Enable; ///< Offset 12 IGD Function 1 Enable
+ UINT8 IgdHpllVco; ///< Offset 13 HPLL VCO
+ UINT8 IgdSciSmiMode; ///< Offset 14 GMCH SMI/SCI mode (0=SCI)
+ UINT8 IgdPAVP; ///< Offset 15 IGD PAVP data
+ UINT8 CurrentDeviceList; ///< Offset 16 Current Attached Device List
+ UINT16 CurrentDisplayState; ///< Offset 17 Current Display State
+ UINT16 NextDisplayState; ///< Offset 19 Next Display State
+ UINT8 NumberOfValidDeviceId; ///< Offset 21 Number of Valid Device IDs
+ UINT32 DeviceId1; ///< Offset 22 Device ID 1
+ UINT32 DeviceId2; ///< Offset 26 Device ID 2
+ UINT32 DeviceId3; ///< Offset 30 Device ID 3
+ UINT32 DeviceId4; ///< Offset 34 Device ID 4
+ UINT32 DeviceId5; ///< Offset 38 Device ID 5
+ UINT32 DeviceId6; ///< Offset 42 Device ID 6
+ UINT32 DeviceId7; ///< Offset 46 Device ID 7
+ UINT32 DeviceId8; ///< Offset 50 Device ID 8
+ UINT32 DeviceId9; ///< Offset 54 Device ID 9
+ UINT32 DeviceId10; ///< Offset 58 Device ID 10
+ UINT32 DeviceId11; ///< Offset 62 Device ID 11
+ UINT32 DeviceId12; ///< Offset 66 Device ID 12
+ UINT32 DeviceId13; ///< Offset 70 Device ID 13
+ UINT32 DeviceId14; ///< Offset 74 Device ID 14
+ UINT32 DeviceId15; ///< Offset 78 Device ID 15
+ UINT32 DeviceIdX; ///< Offset 82 Device ID for eDP device
+ UINT32 NextStateDid1; ///< Offset 86 Next state DID1 for _DGS
+ UINT32 NextStateDid2; ///< Offset 90 Next state DID2 for _DGS
+ UINT32 NextStateDid3; ///< Offset 94 Next state DID3 for _DGS
+ UINT32 NextStateDid4; ///< Offset 98 Next state DID4 for _DGS
+ UINT32 NextStateDid5; ///< Offset 102 Next state DID5 for _DGS
+ UINT32 NextStateDid6; ///< Offset 106 Next state DID6 for _DGS
+ UINT32 NextStateDid7; ///< Offset 110 Next state DID7 for _DGS
+ UINT32 NextStateDid8; ///< Offset 114 Next state DID8 for _DGS
+ UINT32 NextStateDidEdp; ///< Offset 118 Next state DID for eDP
+ UINT8 LidState; ///< Offset 122 Lid State (Lid Open = 1)
+ UINT32 AKsv0; ///< Offset 123 First four bytes of AKSV (manufacturing mode)
+ UINT8 AKsv1; ///< Offset 127 Fifth byte of AKSV (manufacturing mode)
+ UINT8 BrightnessPercentage; ///< Offset 128 Brightness Level Percentage
+ UINT8 AlsEnable; ///< Offset 129 Ambient Light Sensor Enable
+ UINT8 AlsAdjustmentFactor; ///< Offset 130 Ambient Light Adjusment Factor
+ UINT8 LuxLowValue; ///< Offset 131 LUX Low Value
+ UINT8 LuxHighValue; ///< Offset 132 LUX High Value
+ UINT8 ActiveLFP; ///< Offset 133 Active LFP
+ UINT8 ImguAcpiMode; ///< Offset 134 IMGU ACPI device type
+ UINT8 EdpValid; ///< Offset 135 Check for eDP display device
+ UINT8 SgMode; ///< Offset 136 SG Mode (0=Disabled, 1=SG Muxed, 2=SG Muxless, 3=DGPU Only)
+ UINT8 SgFeatureList; ///< Offset 137 SG Feature List
+ UINT8 Pcie0GpioSupport; ///< Offset 138 PCIe0 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ UINT8 Pcie0HoldRstExpanderNo; ///< Offset 139 PCIe0 HLD RST IO Expander Number
+ UINT32 Pcie0HoldRstGpioNo; ///< Offset 140 PCIe0 HLD RST GPIO Number
+ UINT8 Pcie0HoldRstActiveInfo; ///< Offset 144 PCIe0 HLD RST GPIO Active Information
+ UINT8 Pcie0PwrEnExpanderNo; ///< Offset 145 PCIe0 PWR Enable IO Expander Number
+ UINT32 Pcie0PwrEnGpioNo; ///< Offset 146 PCIe0 PWR Enable GPIO Number
+ UINT8 Pcie0PwrEnActiveInfo; ///< Offset 150 PCIe0 PWR Enable GPIO Active Information
+ UINT8 Pcie1GpioSupport; ///< Offset 151 PCIe1 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ UINT8 Pcie1HoldRstExpanderNo; ///< Offset 152 PCIe1 HLD RST IO Expander Number
+ UINT32 Pcie1HoldRstGpioNo; ///< Offset 153 PCIe1 HLD RST GPIO Number
+ UINT8 Pcie1HoldRstActiveInfo; ///< Offset 157 PCIe1 HLD RST GPIO Active Information
+ UINT8 Pcie1PwrEnExpanderNo; ///< Offset 158 PCIe1 PWR Enable IO Expander Number
+ UINT32 Pcie1PwrEnGpioNo; ///< Offset 159 PCIe1 PWR Enable GPIO Number
+ UINT8 Pcie1PwrEnActiveInfo; ///< Offset 163 PCIe1 PWR Enable GPIO Active Information
+ UINT8 Pcie2GpioSupport; ///< Offset 164 PCIe2 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ UINT8 Pcie2HoldRstExpanderNo; ///< Offset 165 PCIe2 HLD RST IO Expander Number
+ UINT32 Pcie2HoldRstGpioNo; ///< Offset 166 PCIe2 HLD RST GPIO Number
+ UINT8 Pcie2HoldRstActiveInfo; ///< Offset 170 PCIe2 HLD RST GPIO Active Information
+ UINT8 Pcie2PwrEnExpanderNo; ///< Offset 171 PCIe2 PWR Enable IO Expander Number
+ UINT32 Pcie2PwrEnGpioNo; ///< Offset 172 PCIe2 PWR Enable GPIO Number
+ UINT8 Pcie2PwrEnActiveInfo; ///< Offset 176 PCIe2 PWR Enable GPIO Active Information
+ UINT16 DelayAfterPwrEn; ///< Offset 177 Delay after power enable for PCIe
+ UINT16 DelayAfterHoldReset; ///< Offset 179 Delay after Hold Reset for PCIe
+ UINT8 Pcie0EpCapOffset; ///< Offset 181 PCIe0 Endpoint Capability Structure Offset
+ UINT32 XPcieCfgBaseAddress; ///< Offset 182 Any Device's PCIe Config Space Base Address
+ UINT16 GpioBaseAddress; ///< Offset 186 GPIO Base Address
+ UINT32 NvIgOpRegionAddress; ///< Offset 188 NVIG opregion address
+ UINT32 NvHmOpRegionAddress; ///< Offset 192 NVHM opregion address
+ UINT32 ApXmOpRegionAddress; ///< Offset 196 AMDA opregion address
+ UINT8 Peg0LtrEnable; ///< Offset 200 Latency Tolerance Reporting Enable
+ UINT8 Peg0ObffEnable; ///< Offset 201 Optimized Buffer Flush and Fill
+ UINT8 Peg1LtrEnable; ///< Offset 202 Latency Tolerance Reporting Enable
+ UINT8 Peg1ObffEnable; ///< Offset 203 Optimized Buffer Flush and Fill
+ UINT8 Peg2LtrEnable; ///< Offset 204 Latency Tolerance Reporting Enable
+ UINT8 Peg2ObffEnable; ///< Offset 205 Optimized Buffer Flush and Fill
+ UINT16 PegLtrMaxSnoopLatency; ///< Offset 206 SA Peg Latency Tolerance Reporting Max Snoop Latency
+ UINT16 PegLtrMaxNoSnoopLatency; ///< Offset 208 SA Peg Latency Tolerance Reporting Max No Snoop Latency
+ UINT8 Peg0PowerDownUnusedBundles; ///< Offset 210 Peg0 Unused Bundle Control
+ UINT8 Peg1PowerDownUnusedBundles; ///< Offset 211 Peg1 Unused Bundle Control
+ UINT8 Peg2PowerDownUnusedBundles; ///< Offset 212 Peg2 Unused Bundle Control
+ UINT8 PackageCstateLimit; ///< Offset 213 The lowest C-state for the package
+ UINT8 PwrDnBundlesGlobalEnable; ///< Offset 214 Pegx Unused Bundle Control Global Enable (0=Disabled, 1=Enabled)
+ UINT64 Mmio64Base; ///< Offset 215 Base of above 4GB MMIO resource
+ UINT64 Mmio64Length; ///< Offset 223 Length of above 4GB MMIO resource
+ UINT32 CpuIdInfo; ///< Offset 231 CPU ID info to get Family Id or Stepping
+ UINT8 Pcie1EpCapOffset; ///< Offset 235 PCIe1 Endpoint Capability Structure Offset
+ UINT8 Pcie2EpCapOffset; ///< Offset 236 PCIe2 Endpoint Capability Structure Offset
+ UINT8 Pcie0SecBusNum; ///< Offset 237 PCIe0 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ UINT8 Pcie1SecBusNum; ///< Offset 238 PCIe1 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ UINT8 Pcie2SecBusNum; ///< Offset 239 PCIe2 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ UINT32 Mmio32Base; ///< Offset 240 Base of below 4GB MMIO resource
+ UINT32 Mmio32Length; ///< Offset 244 Length of below 4GB MMIO resource
+ UINT32 Pcie0WakeGpioNo; ///< Offset 248 PCIe0 RTD3 Device Wake GPIO Number
+ UINT32 Pcie1WakeGpioNo; ///< Offset 252 PCIe1 RTD3 Device Wake GPIO Number
+ UINT32 Pcie2WakeGpioNo; ///< Offset 256 PCIe2 RTD3 Device Wake GPIO Number
+ UINT8 Reserved0[240]; ///< Offset 260:499
+ UINT8 Reserved1[3]; ///< Offset 500:502
+} SYSTEM_AGENT_GLOBAL_NVS_AREA;
+
+#pragma pack(pop)
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
new file mode 100644
index 0000000000..577eaa8ffc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
@@ -0,0 +1,58 @@
+/** @file
+ Interface definition details between System Agent and platform drivers during DXE phase.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_POLICY_H_
+#define _SA_POLICY_H_
+
+#include <SaAccess.h>
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <ConfigBlock/GraphicsDxeConfig.h>
+#include <ConfigBlock/MiscDxeConfig.h>
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gSaPolicyProtocolGuid;
+extern EFI_GUID gGraphicsDxeConfigGuid;
+
+/**
+ Don't change the original SA_POLICY_PROTOCOL_REVISION macro, external
+ modules maybe have consumed this macro in their source code. Directly
+ update the SA_POLICY_PROTOCOL_REVISION version number may cause those
+ external modules to auto mark themselves wrong version info.
+ Always create new version macro for new Policy protocol interface.
+**/
+#define SA_POLICY_PROTOCOL_REVISION 1
+
+/**
+ SA DXE Policy
+
+ The SA_POLICY_PROTOCOL producer drvier is recommended to
+ set all the SA_POLICY_PROTOCOL size buffer zero before init any member parameter,
+ this clear step can make sure no random value for those unknow new version parameters.
+
+ Make sure to update the Revision if any change to the protocol, including the existing
+ internal structure definations.\n
+ Note: Here revision will be bumped up when adding/removing any config block under this structure.\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader; ///< Offset 0-31
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} SA_POLICY_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaAccess.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaAccess.h
new file mode 100644
index 0000000000..5d343ba57a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaAccess.h
@@ -0,0 +1,52 @@
+/** @file
+ Macros to simplify and abstract the interface to PCI configuration.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SAACCESS_H_
+#define _SAACCESS_H_
+
+#include "SaRegs.h"
+
+///
+/// SystemAgent Base Address definition
+///
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND 1
+#endif
+#ifndef STALL_ONE_MILLI_SECOND
+#define STALL_ONE_MILLI_SECOND 1000
+#endif
+
+//
+// SA PCI Express* Port configuration
+//
+#define SA_PEG_BUS_NUM 0x00
+#define SA_PEG_DEV_NUM 0x01
+#define SA_PEG10_DEV_NUM SA_PEG_DEV_NUM
+#define SA_PEG10_FUN_NUM 0x00
+#define SA_PEG11_DEV_NUM SA_PEG_DEV_NUM
+#define SA_PEG11_FUN_NUM 0x01
+#define SA_PEG12_DEV_NUM SA_PEG_DEV_NUM
+#define SA_PEG12_FUN_NUM 0x02
+#define SA_PEG_MAX_FUN 0x03
+
+///
+/// SgMode settings
+///
+typedef enum {
+ SgModeDisabled = 0,
+ SgModeReserved,
+ SgModeMuxless,
+ SgModeDgpu,
+ SgModeMax
+} SG_MODE;
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaPolicyCommon.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaPolicyCommon.h
new file mode 100644
index 0000000000..bfe6011763
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaPolicyCommon.h
@@ -0,0 +1,40 @@
+/** @file
+ Main System Agent Policy structure definition which will contain several config blocks during runtime.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_POLICY_COMMON_H_
+#define _SA_POLICY_COMMON_H_
+
+#include <Uefi.h>
+#include <Library/SmbusLib.h>
+#include <SaAccess.h>
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <ConfigBlock/MemoryConfig.h>
+#include <ConfigBlock/SaMiscPeiPreMemConfig.h>
+#include <ConfigBlock/GraphicsPeiConfig.h>
+#include <ConfigBlock/VtdConfig.h>
+
+
+
+//
+// Extern the GUID for PPI users.
+//
+extern EFI_GUID gSiPolicyPpiGuid;
+extern EFI_GUID gSiPreMemPolicyPpiGuid;
+extern EFI_GUID gSaMiscPeiPreMemConfigGuid;
+extern EFI_GUID gGraphicsPeiConfigGuid;
+extern EFI_GUID gVtdConfigGuid;
+extern EFI_GUID gMemoryConfigGuid;
+extern EFI_GUID gMemoryConfigNoCrcGuid;
+
+#endif // _SA_POLICY_COMMON_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaRegs.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaRegs.h
new file mode 100644
index 0000000000..5f92981f4b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Include/SaRegs.h
@@ -0,0 +1,787 @@
+/** @file
+ Register names for System Agent (SA) registers
+ <b>Conventions</b>:
+ - Prefixes:
+ - Definitions beginning with "R_" are registers
+ - Definitions beginning with "B_" are bits within registers
+ - Definitions beginning with "V_" are meaningful values of bits within the registers
+ - Definitions beginning with "S_" are register sizes
+ - Definitions beginning with "N_" are the bit position
+ - In general, SA registers are denoted by "_SA_" in register names
+ - Registers / bits that are different between SA generations are denoted by
+ "_SA_[generation_name]_" in register/bit names. e.g., "_SA_HSW_"
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a SA generation will be just named
+ as "_SA_" without [generation_name] inserted.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_REGS_H_
+#define _SA_REGS_H_
+
+//
+// DEVICE 0 (Memory Controller Hub)
+//
+#define SA_MC_BUS 0x00
+#define SA_MC_DEV 0x00
+#define SA_MC_FUN 0x00
+#define V_SA_MC_VID 0x8086
+#define R_SA_MC_DEVICE_ID 0x02
+#define R_SA_MC_CAPID0_B 0xE8
+
+//
+// Macros that judge which type a device ID belongs to
+//
+
+//
+// CPU Mobile SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_SKL_MB_ULT_1 0x1904 ///< Skylake Ult (OPI) (2+1F/1.5F/2F/3/3E) Mobile SA DID
+#define V_SA_DEVICE_ID_SKL_MB_ULX_2 0x190C ///< Skylake Ulx (OPI) (2+1F/1.5F/2) SA DID
+#define V_SA_DEVICE_ID_SKL_MB_ULX_3 0x1924 ///< Skylake Ulx (OPI)
+//
+// CPU Halo SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_SKL_HALO_1 0x1900 ///< Skylake Halo (2+2/1) SA DID
+#define V_SA_DEVICE_ID_SKL_HALO_2 0x1910 ///< Skylake Halo (4+2/4E/3FE) SA DID
+#define V_SA_DEVICE_ID_SKL_HALO_3 0x1918 ///< Skylake Halo (4+3E/4E) Embedded SA DID
+//
+// CPU Desktop SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_SKL_DT_1 0x190F ///< Skylake Desktop (2+1F/1.5F/2) SA DID
+#define V_SA_DEVICE_ID_SKL_DT_2 0x191F ///< Skylake Desktop (4+2/4) SA DID
+//
+// CPU Server SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_SKL_SVR_1 0x1908 ///< Skylake Server (2+2/3E) SA DID
+#define V_SA_DEVICE_ID_SKL_SVR_2 0x1918 ///< Skylake Server (4+1/2/4E) SA DID
+
+//
+// KabyLake CPU Mobile SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_KBL_MB_ULT_1 0x5904 ///< Kabylake Ult (OPI) (2+1F/1.5F/2F/3/3E) Mobile SA DID
+#define V_SA_DEVICE_ID_KBLR_MB_ULT_1 0x5914 ///< Kabylake-R Ult Mobile SA DID
+#define V_SA_DEVICE_ID_KBL_MB_ULX_1 0x590C ///< Kabylake Ulx (OPI) (2+1F/1.5F/2) SA DID
+//
+// KabyLake CPU Halo SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_KBL_HALO_1 0x5900 ///< Kabylake Halo (2+2/1) SA DID
+#define V_SA_DEVICE_ID_KBL_HALO_2 0x5910 ///< Kabylake Halo (4+2/4E/3FE) SA DID
+//
+// KabyLake CPU Desktop SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_KBL_DT_1 0x590F ///< Kabylake Desktop (2+1F/1.5F/2) SA DID
+#define V_SA_DEVICE_ID_KBL_DT_2 0x591F ///< Kabylake Desktop (4+1.5F/2/4) SA DID
+//
+// KabyLake CPU Server SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_KBL_SVR_1 0x5908 ///< Kabylake Server (2+2/3E) SA DID
+#define V_SA_DEVICE_ID_KBL_SVR_2 0x5918 ///< Kabylake Server (4+1/2/4E) SA DID
+//
+// CoffeeLake CPU Desktop SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_CFL_DT 0x3EC2 ///< CoffeeLake Desktop (6+2) SA DID
+
+///
+/// Device IDs that are Mobile specific B0:D0:F0
+///
+#define IS_SA_DEVICE_ID_MOBILE(DeviceId) \
+ ( \
+ (DeviceId == V_SA_DEVICE_ID_SKL_MB_ULT_1) || \
+ (DeviceId == V_SA_DEVICE_ID_SKL_MB_ULX_2) || \
+ (DeviceId == V_SA_DEVICE_ID_SKL_MB_ULX_3) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_MB_ULT_1) || \
+ (DeviceId == V_SA_DEVICE_ID_KBLR_MB_ULT_1) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_MB_ULX_1) \
+ )
+
+///
+/// Device IDs that are Desktop specific B0:D0:F0
+///
+#define IS_SA_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ (DeviceId == V_SA_DEVICE_ID_SKL_DT_1) || \
+ (DeviceId == V_SA_DEVICE_ID_SKL_DT_2) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_DT_1) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_DT_2) || \
+ (DeviceId == V_SA_DEVICE_ID_CFL_DT) \
+ )
+
+///
+/// Device IDS that are Server specific B0:D0:F0
+///
+#define IS_SA_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ (DeviceId == V_SA_DEVICE_ID_SKL_SVR_1) || \
+ (DeviceId == V_SA_DEVICE_ID_SKL_SVR_2) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_SVR_1) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_SVR_2) \
+ )
+
+///
+/// Device IDs that are Halo specific B0:D0:F0
+///
+#define IS_SA_DEVICE_ID_HALO(DeviceId) \
+ ( \
+ (DeviceId == V_SA_DEVICE_ID_SKL_HALO_1) || \
+ (DeviceId == V_SA_DEVICE_ID_SKL_HALO_2) || \
+ (DeviceId == V_SA_DEVICE_ID_SKL_HALO_3) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_HALO_1) || \
+ (DeviceId == V_SA_DEVICE_ID_KBL_HALO_2) \
+ )
+
+/**
+ <b>Description</b>:
+ This is the base address for the PCI Express Egress Port MMIO Configuration space. There is no physical memory within this 4KB window that can be addressed. The 4KB reserved by this register does not alias to any PCI 2.3 compliant memory mapped space. On reset, the EGRESS port MMIO configuration space is disabled and must be enabled by writing a 1 to PXPEPBAREN [Dev 0, offset 40h, bit 0].
+ All the bits in this register are locked in LT mode.
+**/
+#define R_SA_PXPEPBAR (0x40)
+//
+// Description of PXPEPBAREN (0:0)
+// - 0: PXPEPBAR is disabled and does not claim any memory
+// - 1: PXPEPBAR memory mapped accesses are claimed and decoded appropriately
+// - This register is locked by LT.
+//
+#define N_SA_PXPEPBAR_PXPEPBAREN_OFFSET (0x0)
+#define S_SA_PXPEPBAR_PXPEPBAREN_WIDTH (0x1)
+#define B_SA_PXPEPBAR_PXPEPBAREN_MASK (0x1)
+#define V_SA_PXPEPBAR_PXPEPBAREN_DEFAULT (0x0)
+//
+// Description of PXPEPBAR (12:38)
+// - This field corresponds to bits 38 to 12 of the base address PCI Express Egress Port MMIO configuration space. BIOS will program this register resulting in a base address for a 4KB block of contiguous memory address space. This register ensures that a naturally aligned 4KB space is allocated within the first 512GB of addressable memory space. System Software uses this base address to program the PCI Express Egress Port MMIO register set. All the bits in this register are locked in LT mode.
+//
+#define N_SA_PXPEPBAR_PXPEPBAR_OFFSET (0xc)
+#define S_SA_PXPEPBAR_PXPEPBAR_WIDTH (0x1b)
+#define B_SA_PXPEPBAR_PXPEPBAR_MASK (0x7ffffff000)
+#define V_SA_PXPEPBAR_PXPEPBAR_DEFAULT (0x0)
+
+/**
+ <b>Description</b>:
+ - This is the base address for the Host Memory Mapped Configuration space. There is no physical memory within this 32KB window that can be addressed. The 32KB reserved by this register does not alias to any PCI 2.3 compliant memory mapped space. On reset, the Host MMIO Memory Mapped Configuation space is disabled and must be enabled by writing a 1 to MCHBAREN [Dev 0, offset48h, bit 0].
+ - All the bits in this register are locked in LT mode.
+ - The register space contains memory control, initialization, timing, and buffer strength registers; clocking registers; and power and thermal management registers.
+**/
+#define R_SA_MCHBAR (0x48)
+/**
+ Description of MCHBAREN (0:0)
+ - 0: MCHBAR is disabled and does not claim any memory
+ - 1: MCHBAR memory mapped accesses are claimed and decoded appropriately
+ - This register is locked by LT.
+**/
+#define N_SA_MCHBAR_MCHBAREN_OFFSET (0x0)
+#define S_SA_MCHBAR_MCHBAREN_WIDTH (0x1)
+#define B_SA_MCHBAR_MCHBAREN_MASK (0x1)
+#define V_SA_MCHBAR_MCHBAREN_DEFAULT (0x0)
+/**
+ Description of MCHBAR (15:38)
+ - This field corresponds to bits 38 to 15 of the base address Host Memory Mapped configuration space. BIOS will program this register resulting in a base address for a 32KB block of contiguous memory address space. This register ensures that a naturally aligned 32KB space is allocated within the first 512GB of addressable memory space. System Software uses this base address to program the Host Memory Mapped register set. All the bits in this register are locked in LT mode.
+**/
+#define N_SA_MCHBAR_MCHBAR_OFFSET (0xf)
+#define S_SA_MCHBAR_MCHBAR_WIDTH (0x18)
+#define B_SA_MCHBAR_MCHBAR_MASK (0x7fffff8000ULL)
+#define V_SA_MCHBAR_MCHBAR_DEFAULT (0x0)
+
+/**
+ <b>Description</b>:
+ - All the bits in this register are LT lockable.
+**/
+#define R_SA_GGC (0x50)
+/**
+ Description of GGCLCK (0:0)
+ - When set to 1b, this bit will lock all bits in this register.
+**/
+#define N_SA_GGC_GGCLCK_OFFSET (0x0)
+#define S_SA_GGC_GGCLCK_WIDTH (0x1)
+#define B_SA_GGC_GGCLCK_MASK (0x1)
+#define V_SA_GGC_GGCLCK_DEFAULT (0x0)
+/**
+ Description of IVD (1:1)
+ - 0: Enable. Device 2 (IGD) claims VGA memory and IO cycles, the Sub-Class Code within Device 2 Class Code register is 00.
+ - 1: Disable. Device 2 (IGD) does not claim VGA cycles (Mem and IO), and the Sub- Class Code field within Device 2 function 0 Class Code register is 80.
+ - BIOS Requirement: BIOS must not set this bit to 0 if the GMS field (bits 7:3 of this register) pre-allocates no memory.
+ - This bit MUST be set to 1 if Device 2 is disabled either via a fuse or fuse override (CAPID0[46] = 1) or via a register (DEVEN[3] = 0).
+ - This register is locked by LT lock.
+**/
+#define N_SA_GGC_IVD_OFFSET (0x1)
+#define S_SA_GGC_IVD_WIDTH (0x1)
+#define B_SA_GGC_IVD_MASK (0x2)
+#define V_SA_GGC_IVD_DEFAULT (0x0)
+/**
+ For SKL
+ Description of GMS (8:15)
+ - This field is used to select the amount of Main Memory that is pre-allocated to support the Internal Graphics device in VGA (non-linear) and Native (linear) modes. The BIOS ensures that memory is pre-allocated only when Internal graphics is enabled.
+ - This register is also LT lockable.
+ - Valid options are 0 (0x0) to 2048MB (0x40) in multiples of 32 MB
+ - Default is 64MB
+ - All other values are reserved
+ - Hardware does not clear or set any of these bits automatically based on IGD being disabled/enabled.
+ - BIOS Requirement: BIOS must not set this field to 0h if IVD (bit 1 of this register) is 0.
+**/
+#define N_SKL_SA_GGC_GMS_OFFSET (0x8)
+#define S_SKL_SA_GGC_GMS_WIDTH (0x8)
+#define B_SKL_SA_GGC_GMS_MASK (0xff00)
+#define V_SKL_SA_GGC_GMS_DEFAULT (0x01)
+
+/**
+ For SKL
+ Description of GGMS (6:7)
+ - This field is used to select the amount of Main Memory that is pre-allocated to support the Internal Graphics Translation Table. The BIOS ensures that memory is pre-allocated only when Internal graphics is enabled.
+ - GSM is assumed to be a contiguous physical DRAM space with DSM, and BIOS needs to allocate a contiguous memory chunk. Hardware will derive the base of GSM from DSM only using the GSM size programmed in the register.
+ - Valid options:
+ - 0h: 0 MB of memory pre-allocated for GTT.
+ - 1h: 2 MB of memory pre-allocated for GTT.
+ - 2h: 4 MB of memory pre-allocated for GTT. (default)
+ - 3h: 8 MB of memory pre-allocated for GTT.
+ - Others: Reserved
+ - Hardware functionality in case of programming this value to Reserved is not guaranteed.
+**/
+#define N_SKL_SA_GGC_GGMS_OFFSET (0x6)
+#define S_SKL_SA_GGC_GGMS_WIDTH (0x2)
+#define B_SKL_SA_GGC_GGMS_MASK (0xc0)
+#define V_SKL_SA_GGC_GGMS_DEFAULT (2)
+#define V_SKL_SA_GGC_GGMS_DIS 0
+#define V_SKL_SA_GGC_GGMS_2MB 1
+#define V_SKL_SA_GGC_GGMS_4MB 2
+#define V_SKL_SA_GGC_GGMS_8MB 3
+
+/**
+ Description:
+ - Allows for enabling/disabling of PCI devices and functions that are within the CPU package. The table below the bit definitions describes the behavior of all combinations of transactions to devices controlled by this register.
+ All the bits in this register are LT Lockable.
+**/
+#define R_SA_DEVEN (0x54)
+#define B_SA_DEVEN_D2EN_MASK (0x10)
+
+/**
+ Description
+ - Protected Audio Video Path Control
+ - All the bits in this register are locked by LT. When locked the R/W bits are RO.
+**/
+#define R_SA_PAVPC (0x58)
+/**
+ Description of PCME (0:0)
+ - This field enables Protected Content Memory within Graphics Stolen Memory.
+ - This register is locked (becomes read-only) when PAVPLCK = 1b.
+ - This register is read-only (stays at 0b) when PAVP fuse is set to "disabled"
+ - 0: Protected Content Memory is disabled
+ - 1: Protected Content Memory is enabled
+**/
+#define N_SA_PAVPC_PCME_OFFSET (0x0)
+#define S_SA_PAVPC_PCME_WIDTH (0x1)
+#define B_SA_PAVPC_PCME_MASK (0x1)
+#define V_SA_PAVPC_PCME_MASK (0x0)
+/**
+ Description of PAVPE (1:1)
+ - 0: PAVP path is disabled
+ - 1: PAVP path is enabled
+ - This register is locked (becomes read-only) when PAVPLCK = 1b
+ - This register is read-only (stays at 0b) when PAVP capability is set to "disabled" as defined by CAPID0_B[PAVPE].
+**/
+#define N_SA_PAVPC_PAVPE_OFFSET (0x1)
+#define S_SA_PAVPC_PAVPE_WIDTH (0x1)
+#define B_SA_PAVPC_PAVPE_MASK (0x2)
+#define V_SA_PAVPC_PAVPE_DEFAULT (0x0)
+/**
+ Description of PAVPLCK (2:2)
+ - This bit will lock all writeable contents in this register when set (including itself).
+ - This bit will be locked if PAVP is fused off.
+**/
+#define N_SA_PAVPC_PAVPLCK_OFFSET (0x2)
+#define S_SA_PAVPC_PAVPLCK_WIDTH (0x1)
+#define B_SA_PAVPC_PAVPLCK_MASK (0x4)
+#define V_SA_PAVPC_PAVPLCK_DEFAULT (0x0)
+/**
+ Description of PCMBASE (20:31)
+ - This field is used to set the base of Protected Content Memory.
+ - This corresponds to bits 31:20 of the system memory address range, giving a 1MB granularity. This value MUST be at least 1MB above the base and below the top of stolen memory.
+ - This register is locked (becomes read-only) when PAVPE = 1b.
+**/
+#define N_SA_PAVPC_PCMBASE_OFFSET (0x14)
+#define S_SA_PAVPC_PCMBASE_WIDTH (0xc)
+#define B_SA_PAVPC_PCMBASE_MASK (0xfff00000)
+#define V_SA_PAVPC_PCMBASE_DEFAULT (0x0)
+
+#define R_SA_DPR (0x5c) ///< DMA protected range register
+/**
+ Description of LOCK (0:0)
+ - This bit will lock all writeable settings in this register, including itself.
+**/
+#define N_SA_DPR_LOCK_OFFSET (0x0)
+#define S_SA_DPR_LOCK_WIDTH (0x1)
+#define B_SA_DPR_LOCK_MASK (0x1)
+#define V_SA_DPR_LOCK_DEFAULT (0x0)
+/**
+ Description of PRS (1:1)
+ - This field indicates the status of DPR.
+ - 0: DPR protection disabled
+ - 1: DPR protection enabled
+**/
+#define N_SA_DPR_PRS_OFFSET (0x1)
+#define S_SA_DPR_PRS_WIDTH (0x1)
+#define B_SA_DPR_PRS_MASK (0x2)
+#define V_SA_DPR_PRS_DEFAULT (0x0)
+/**
+ Description of EPM (2:2)
+ - This field controls DMA accesses to the DMA Protected Range (DPR) region.
+ - 0: DPR is disabled
+ - 1: DPR is enabled. All DMA requests accessing DPR region are blocked.
+ - HW reports the status of DPR enable/disable through the PRS field in this register.
+**/
+#define N_SA_DPR_EPM_OFFSET (0x2)
+#define S_SA_DPR_EPM_WIDTH (0x1)
+#define B_SA_DPR_EPM_MASK (0x4)
+#define V_SA_DPR_EPM_DEFAULT (0x0)
+/**
+ Description of DPRSIZE (11:4)
+ - This field is used to specify the size of memory protected from DMA access in MB
+ - The maximum amount of memory that will be protected is 255MB
+ - The Top of protected range is the base of TSEG-1
+**/
+#define N_DPR_DPRSIZE_OFFSET (0x4)
+#define V_DPR_DPRSIZE_WIDTH (0x8)
+#define V_DPR_DPRSIZE_MASK (0xFF0)
+#define V_DPR_DPRSIZE_DEFAULT (0x0)
+/**
+ Description of TOPOFDPR (31:20)
+ - This is the Top address 1 of DPR - Base of TSEG
+**/
+#define N_SA_DPR_TOPOFDPR_OFFSET (20)
+#define S_SA_DPR_TOPOFDPR_WIDTH (0xC)
+#define B_SA_DPR_TOPOFDPR_MASK (0xFFF00000)
+#define V_SA_DPR_TOPOFDPR_DEFAULT (0x0)
+
+/**
+ This is the base address for the Root Complex configuration space. This window of addresses contains the Root Complex Register set for the PCI Express Hierarchy associated with the Host Bridge. There is no physical memory within this 4KB window that can be addressed. The 4KB reserved by this register does not alias to any PCI 2.3 compliant memory mapped space. On reset, the Root Complex configuration space is disabled and must be enabled by writing a 1 to DMIBAREN [Dev 0, offset 68h, bit 0] All the bits in this register are locked in LT mode.
+**/
+#define R_SA_DMIBAR (0x68)
+/**
+ Description of DMIBAREN (0:0)
+ - 0: DMIBAR is disabled and does not claim any memory
+ - 1: DMIBAR memory mapped accesses are claimed and decoded appropriately
+ - This register is locked by LT.
+**/
+#define N_SA_DMIBAR_DMIBAREN_OFFSET (0x0)
+#define S_SA_DMIBAR_DMIBAREN_WIDTH (0x1)
+#define B_SA_DMIBAR_DMIBAREN_MASK (0x1)
+#define V_SA_DMIBAR_DMIBAREN_DEFAULT (0x0)
+/**
+ Description of DMIBAR (12:38)
+ - This field corresponds to bits 38 to 12 of the base address DMI configuration space. BIOS will program this register resulting in a base address for a 4KB block of contiguous memory address space. This register ensures that a naturally aligned 4KB space is allocated within the first 512GB of addressable memory space. System Software uses this base address to program the DMI register set. All the Bits in this register are locked in LT mode.
+**/
+#define N_SA_DMIBAR_DMIBAR_OFFSET (0xc)
+#define S_SA_DMIBAR_DMIBAR_WIDTH (0x1b)
+#define B_SA_DMIBAR_DMIBAR_MASK (0x7ffffff000)
+#define V_SA_DMIBAR_DMIBAR_DEFAULT (0x0)
+
+/**
+ Description:
+ - This register determines the Mask Address register of the memory range that is pre-allocated to the Manageability Engine. Together with the MESEG_BASE register it controls the amount of memory allocated to the ME.
+ - This register is locked by LT.
+**/
+#define R_SA_MESEG_MASK (0x78)
+/**
+ Description of MELCK (10:10)
+ - This field indicates whether all bits in the MESEG_BASE and MESEG_MASK registers are locked. When locked, updates to any field for these registers must be dropped.
+**/
+#define N_SA_MESEG_MASK_MELCK_OFFSET (0xa)
+#define S_SA_MESEG_MASK_MELCK_WIDTH (0x1)
+#define B_SA_MESEG_MASK_MELCK_MASK (0x400)
+#define V_SA_MESEG_MASK_MELCK_DEFAULT (0x0)
+/**
+ Description of ME_STLEN_EN (11:11)
+ - Indicates whether the ME stolen Memory range is enabled or not.
+**/
+#define N_SA_MESEG_MASK_ME_STLEN_EN_OFFSET (0xb)
+#define S_SA_MESEG_MASK_ME_STLEN_EN_WIDTH (0x1)
+#define V_SA_MESEG_MASK_ME_STLEN_EN_DEFAULT (0x0)
+#define B_SA_MESEG_MASK_ME_STLEN_EN_MASK (0x800)
+/**
+ Description of MEMASK (20:38)
+ - This field indicates the bits that must match MEBASE in order to qualify as an ME Memory Range access.
+ - For example, if the field is set to 7FFFFh, then ME Memory is 1MB in size.
+ - Another example is that if the field is set to 7FFFEh, then ME Memory is 2MB in size.
+ - In other words, the size of ME Memory Range is limited to power of 2 times 1MB.
+**/
+#define N_SA_MESEG_MASK_MEMASK_OFFSET (0x14)
+#define S_SA_MESEG_MASK_MEMASK_WIDTH (0x13)
+#define V_SA_MESEG_MASK_MEMASK_DEFAULT (0x0)
+#define B_SA_MESEG_MASK_MEMASK_MASK (0x7ffff00000)
+/**
+ Description:
+ - This register controls the read, write and shadowing attributes of the BIOS range from F_0000h to F_FFFFh. The Uncore allows programmable memory attributes on 13 legacy memory segments of various sizes in the 768KB to 1MB address range. Seven Programmable Attribute Map (PAM) registers are used to support these features. Cacheability of these areas is controlled via the MTRR register in the core.
+ - Two bits are used to specify memory attributes for each memory segment. These bits apply to host accesses to the PAM areas. These attributes are:
+ - RE - Read Enable. When RE=1, the host read accesses to the corresponding memory segment are claimed by the Uncore and directed to main memory. Conversely, when RE=0, the host read accesses are directed to DMI.
+ - WE - Write Enable. When WE=1, the host write accesses to the corresponding memory segment are claimed by the Uncore and directed to main memory. Conversely, when WE=0, the host read accesses are directed to DMI.
+ - The RE and WE attributes permit a memory segment to be Read Only, Write Only, Read/Write or Disabled. For example, if a memory segment has RE=1 and WE=0, the segment is Read Only.
+**/
+#define R_SA_PAM0 (0x80)
+///
+/// Description:
+/// This register controls the read, write and shadowing attributes of the BIOS range from E_0000h to E_7FFFh. The Uncore allows programmable memory attributes on 13 legacy memory segments of various sizes in the 768KB to 1MB address range. Seven Programmable Attribute Map (PAM) registers are used to support these features. Cacheability of these areas is controlled via the MTRR register in the core.
+/// Two bits are used to specify memory attributes for each memory segment. These bits apply to host accesses to the PAM areas. These attributes are:
+/// RE - Read Enable. When RE=1, the host read accesses to the corresponding memory segment are claimed by the Uncore and directed to main memory. Conversely, when RE=0, the host read accesses are directed to DMI.
+/// WE - Write Enable. When WE=1, the host write accesses to the corresponding memory segment are claimed by the Uncore and directed to main memory. Conversely, when WE=0, the host read accesses are directed to DMI.
+/// The RE and WE attributes permit a memory segment to be Read Only, Write Only, Read/Write or Disabled. For example, if a memory segment has RE=1 and WE=0, the segment is Read Only.
+///
+#define R_SA_PAM5 (0x85)
+///
+/// Description:
+/// This register controls the read, write and shadowing attributes of the BIOS range from E_8000h to E_FFFFh. The Uncore allows programmable memory attributes on 13 legacy memory segments of various sizes in the 768KB to 1MB address range. Seven Programmable Attribute Map (PAM) registers are used to support these features. Cacheability of these areas is controlled via the MTRR register in the core.
+/// Two bits are used to specify memory attributes for each memory segment. These bits apply to host accesses to the PAM areas. These attributes are:
+/// RE - Read Enable. When RE=1, the host read accesses to the corresponding memory segment are claimed by the Uncore and directed to main memory. Conversely, when RE=0, the host read accesses are directed to DMI.
+/// WE - Write Enable. When WE=1, the host write accesses to the corresponding memory segment are claimed by the Uncore and directed to main memory. Conversely, when WE=0, the host read accesses are directed to DMI.
+/// The RE and WE attributes permit a memory segment to be Read Only, Write Only, Read/Write or Disabled. For example, if a memory segment has RE=1 and WE=0, the segment is Read Only.
+///
+#define R_SA_PAM6 (0x86)
+///
+/// Description:
+/// The SMRAMC register controls how accesses to Compatible SMRAM spaces are treated. The Open, Close and Lock bits function only when G_SMRAME bit is set to 1. Also, the Open bit must be reset before the Lock bit is set.
+///
+#define R_SA_SMRAMC (0x88)
+#define B_SA_SMRAMC_D_LCK_MASK (0x10)
+#define B_SA_SMRAMC_D_CLS_MASK (0x20)
+#define B_SA_SMRAMC_D_OPEN_MASK (0x40)
+///
+/// Description:
+///
+#define R_SA_REMAPBASE (0x90)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_REMAPBASE_LOCK_OFFSET (0x0)
+#define S_SA_REMAPBASE_LOCK_WIDTH (0x1)
+#define B_SA_REMAPBASE_LOCK_MASK (0x1)
+#define V_SA_REMAPBASE_LOCK_DEFAULT (0x0)
+///
+/// Description of REMAPBASE (20:38)
+/// The value in this register defines the lower boundary of the Remap window. The Remap window is inclusive of this address. In the decoder A[19:0] of the Remap Base Address are assumed to be 0's. Thus the bottom of the defined memory range will be aligned to a 1MB boundary.
+/// When the value in this register is greater than the value programmed into the Remap Limit register, the Remap window is disabled.
+/// These bits are LT lockable.
+///
+#define N_SA_REMAPBASE_REMAPBASE_OFFSET (0x14)
+#define S_SA_REMAPBASE_REMAPBASE_WIDTH (0x13)
+#define V_SA_REMAPBASE_REMAPBASE_DEFAULT (0x7ffff00000)
+#define B_SA_REMAPBASE_REMAPBASE_MASK (0x7ffff00000)
+
+///
+/// Description:
+///
+#define R_SA_REMAPLIMIT (0x98)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_REMAPLIMIT_LOCK_OFFSET (0x0)
+#define S_SA_REMAPLIMIT_LOCK_WIDTH (0x1)
+#define B_SA_REMAPLIMIT_LOCK_MASK (0x1)
+#define V_SA_REMAPLIMIT_LOCK_DEFAULT (0x0)
+///
+/// Description of REMAPLMT (20:38)
+/// The value in this register defines the upper boundary of the Remap window. The Remap window is inclusive of this address. In the decoder A[19:0] of the remap limit address are assumed to be F's. Thus the top of the defined range will be one byte less than a 1MB boundary.
+/// When the value in this register is less than the value programmed into the Remap Base register, the Remap window is disabled.
+/// These Bits are LT lockable.
+///
+#define N_SA_REMAPLIMIT_REMAPLMT_OFFSET (0x14)
+#define S_SA_REMAPLIMIT_REMAPLMT_WIDTH (0x13)
+#define V_SA_REMAPLIMIT_REMAPLMT_DEFAULT (0x0)
+#define B_SA_REMAPLIMIT_REMAPLMT_MASK (0x7ffff00000)
+
+///
+/// Description:
+/// This Register contains the size of physical memory. BIOS determines the memory size reported to the OS using this Register.
+///
+#define R_SA_TOM (0xa0)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_TOM_LOCK_OFFSET (0x0)
+#define S_SA_TOM_LOCK_WIDTH (0x1)
+#define B_SA_TOM_LOCK_MASK (0x1)
+#define V_SA_TOM_LOCK_DEFAULT (0x0)
+
+///
+/// Description of TOM (20:38)
+/// This register reflects the total amount of populated physical memory. This is NOT necessarily the highest main memory address (holes may exist in main memory address map due to addresses allocated for memory mapped IO). These bits correspond to address bits 38:20 (1MB granularity). Bits 19:0 are assumed to be 0. All the bits in this register are locked in LT mode.
+///
+#define N_SA_TOM_TOM_OFFSET (0x14)
+#define S_SA_TOM_TOM_WIDTH (0x13)
+#define B_SA_TOM_TOM_MASK (0x7ffff00000)
+#define V_SA_TOM_TOM_DEFAULT (0x7ffff00000)
+
+///
+/// Description:
+/// This 64 bit register defines the Top of Upper Usable DRAM.
+/// Configuration software must set this value to TOM minus all EP stolen memory if reclaim is disabled. If reclaim is enabled, this value must be set to reclaim limit + 1byte, 1MB aligned, since reclaim limit is 1MB aligned. Address bits 19:0 are assumed to be 000_0000h for the purposes of address comparison. The Host interface positively decodes an address towards DRAM if the incoming address is less than the value programmed in this register and greater than or equal to 4GB.
+/// BIOS Restriction: Minimum value for TOUUD is 4GB.
+/// These bits are LT lockable.
+///
+#define R_SA_TOUUD (0xa8)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_TOUUD_LOCK_OFFSET (0x0)
+#define S_SA_TOUUD_LOCK_WIDTH (0x1)
+#define B_SA_TOUUD_LOCK_MASK (0x1)
+#define V_SA_TOUUD_LOCK_DEFAULT (0x0)
+///
+/// Description of TOUUD (20:38)
+/// This register contains bits 38 to 20 of an address one byte above the maximum DRAM memory above 4G that is usable by the operating system. Configuration software must set this value to TOM minus all EP stolen memory if reclaim is disabled. If reclaim is enabled, this value must be set to reclaim limit 1MB aligned since reclaim limit + 1byte is 1MB aligned. Address bits 19:0 are assumed to be 000_0000h for the purposes of address comparison. The Host interface positively decodes an address towards DRAM if the incoming address is less than the value programmed in this register and greater than 4GB.
+/// All the bits in this register are locked in LT mode.
+///
+#define N_SA_TOUUD_TOUUD_OFFSET (0x14)
+#define S_SA_TOUUD_TOUUD_WIDTH (0x13)
+#define B_SA_TOUUD_TOUUD_MASK (0x7ffff00000ULL)
+#define V_SA_TOUUD_TOUUD_DEFAULT (0x0)
+
+///
+/// Description:
+/// This register contains the base address of graphics data stolen DRAM memory. BIOS determines the base of graphics data stolen memory by subtracting the graphics data stolen memory size (PCI Device 0 offset 52 bits 7:4) from TOLUD (PCI Device 0 offset BC bits 31:20).
+///
+#define R_SA_BDSM (0xb0)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_BDSM_LOCK_OFFSET (0x0)
+#define S_SA_BDSM_LOCK_WIDTH (0x1)
+#define B_SA_BDSM_LOCK_MASK (0x1)
+#define V_SA_BDSM_LOCK_DEFAULT (0x0)
+///
+/// Description of BDSM (20:31)
+/// This register contains bits 31 to 20 of the base address of stolen DRAM memory. BIOS determines the base of graphics stolen memory by subtracting the graphics stolen memory size (PCI Device 0 offset 52 bits 6:4) from TOLUD (PCI Device 0 offset BC bits 31:20).
+///
+#define N_SA_BDSM_BDSM_OFFSET (0x14)
+#define S_SA_BDSM_BDSM_WIDTH (0xc)
+#define B_SA_BDSM_BDSM_MASK (0xfff00000)
+#define V_SA_BDSM_BDSM_DEFAULT (0x0)
+
+///
+/// Description:
+/// This register contains the base address of stolen DRAM memory for the GTT. BIOS determines the base of GTT stolen memory by subtracting the GTT graphics stolen memory size (PCI Device 0 offset 52 bits 9:8) from the Graphics Base of Data Stolen Memory (PCI Device 0 offset B0 bits 31:20).
+///
+#define R_SA_BGSM (0xb4)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_BGSM_LOCK_OFFSET (0x0)
+#define S_SA_BGSM_LOCK_WIDTH (0x1)
+#define B_SA_BGSM_LOCK_MASK (0x1)
+#define V_SA_BGSM_LOCK_DEFAULT (0x0)
+///
+/// Description of BGSM (20:31)
+/// This register contains the base address of stolen DRAM memory for the GTT. BIOS determines the base of GTT stolen memory by subtracting the GTT graphics stolen memory size (PCI Device 0 offset 52 bits 11:8) from the Graphics Base of Data Stolen Memory (PCI Device 0 offset B0 bits 31:20).
+///
+#define N_SA_BGSM_BGSM_OFFSET (0x14)
+#define S_SA_BGSM_BGSM_WIDTH (0xc)
+#define B_SA_BGSM_BGSM_MASK (0xfff00000)
+#define V_SA_BGSM_BGSM_DEFAULT (0x0)
+
+///
+/// Description:
+/// This register contains the base address of TSEG DRAM memory. BIOS determines the base of TSEG memory which must be at or below Graphics Base of GTT Stolen Memory (PCI Device 0 Offset B4 bits 31:20).
+///
+#define R_SA_TSEGMB (0xb8)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_TSEGMB_LOCK_OFFSET (0x0)
+#define S_SA_TSEGMB_LOCK_WIDTH (0x1)
+#define B_SA_TSEGMB_LOCK_MASK (0x1)
+#define V_SA_TSEGMB_LOCK_DEFAULT (0x0)
+///
+/// Description of TSEGMB (20:31)
+/// This register contains the base address of TSEG DRAM memory. BIOS determines the base of TSEG memory which must be at or below Graphics Base of GTT Stolen Memory (PCI Device 0 Offset B4 bits 31:20).
+///
+#define N_SA_TSEGMB_TSEGMB_OFFSET (0x14)
+#define S_SA_TSEGMB_TSEGMB_WIDTH (0xc)
+#define B_SA_TSEGMB_TSEGMB_MASK (0xfff00000)
+#define V_SA_TSEGMB_TSEGMB_DEFAULT (0x0)
+
+///
+/// Description:
+/// This register contains the Top of low memory address.
+///
+#define R_SA_TOLUD (0xbc)
+///
+/// Description of LOCK (0:0)
+/// This bit will lock all writeable settings in this register, including itself.
+///
+#define N_SA_TOLUD_LOCK_OFFSET (0x0)
+#define S_SA_TOLUD_LOCK_WIDTH (0x1)
+#define B_SA_TOLUD_LOCK_MASK (0x1)
+#define V_SA_TOLUD_LOCK_DEFAULT (0x0)
+///
+/// Description of TOLUD (20:31)
+/// This register contains bits 31 to 20 of an address one byte above the maximum DRAM memory below 4G that is usable by the operating system. Address bits 31 down to 20 programmed to 01h implies a minimum memory size of 1MB. Configuration software must set this value to the smaller of the following 2 choices: maximum amount memory in the system minus ME stolen memory plus one byte or the minimum address allocated for PCI memory. Address bits 19:0 are assumed to be 0_0000h for the purposes of address comparison. The Host interface positively decodes an address towards DRAM if the incoming address is less than the value programmed in this register.
+/// The Top of Low Usable DRAM is the lowest address above both Graphics Stolen memory and Tseg. BIOS determines the base of Graphics Stolen Memory by subtracting the Graphics Stolen Memory Size from TOLUD and further decrements by Tseg size to determine base of Tseg. All the Bits in this register are locked in LT mode.
+/// This register must be 1MB aligned when reclaim is enabled.
+///
+#define N_SA_TOLUD_TOLUD_OFFSET (0x14)
+#define S_SA_TOLUD_TOLUD_WIDTH (0xc)
+#define V_SA_TOLUD_TOLUD_DEFAULT (0x100000)
+#define B_SA_TOLUD_TOLUD_MASK (0xfff00000)
+
+#define R_SA_MC_CAPID0_A_OFFSET 0xE4
+
+#define R_SA_MCHBAR_BIOS_RESET_CPL_OFFSET 0x5DA8
+//
+// Thermal Management Controls
+//
+///
+/// Device 2 Register Equates
+//
+// The following equates must be reviewed and revised when the specification is ready.
+//
+#define SA_IGD_BUS 0x00
+#define SA_IGD_DEV 0x02
+#define SA_IGD_FUN_0 0x00
+#define SA_IGD_FUN_1 0x01
+#define SA_IGD_DEV_FUN (SA_IGD_DEV << 3)
+#define SA_IGD_BUS_DEV_FUN (SA_MC_BUS << 8) + SA_IGD_DEV_FUN
+#define V_SA_IGD_VID 0x8086
+#define SA_GT_APERTURE_SIZE_256MB 1 ///< 256MB is the recommanded GT Aperture Size as per BWG.
+
+///
+/// For SKL IGD
+///
+#define V_SA_PCI_DEV_2_GT1_SULTM_ID 0x01906 ///< Dev2-SKL ULT GT1 (2+1F) Mobile
+#define V_SA_PCI_DEV_2_GT15F_SULTM_ID 0x01913 ///< Dev2-SKL ULT GT1.5 (2+1.5F) Mobile
+#define V_SA_PCI_DEV_2_GT2_SULTM_ID 0x01916 ///< Dev2-SKL ULT GT2 (2+2) Mobile
+#define V_SA_PCI_DEV_2_GT2F_SULTM_ID 0x01921 ///< Dev2-SKL ULT GT2 (2+2F) Mobile
+#define V_SA_PCI_DEV_2_GT3_SULTM_ID 0x01926 ///< Dev2-SKL ULT GT3 (3+3/3E) Mobile
+#define V_SA_PCI_DEV_2_GT1_SHALM_ID 0x0190B ///< Dev2-SKL Halo GT1 (2+1)
+#define V_SA_PCI_DEV_2_GT2_SHALM_ID 0x0191B ///< Dev2-SKL Halo GT2 (4/2+2)
+#define V_SA_PCI_DEV_2_GT3_SHALM_ID 0x0192B ///< Dev2-SKL Halo GT3 (4+3FE)
+#define V_SA_PCI_DEV_2_GT4_SHALM_ID 0x0193B ///< Dev2-SKL Halo GT4 (4+4E)
+#define V_SA_PCI_DEV_2_GT3_SHALM_EMB_ID 0x0192D ///< Dev2-SKL Halo GT3 (4+3E) Embedded
+#define V_SA_PCI_DEV_2_GT4_SHALM_EMB_ID 0x0193D ///< Dev2-SKL Halo GT4 (4+4E) Embedded
+#define V_SA_PCI_DEV_2_GT1_SULXM_ID 0x0190E ///< Dev2-SKL ULX GT1(2+1F) Mobile
+#define V_SA_PCI_DEV_2_GT15_SULXM_ID 0x01915 ///< Dev2-SKL ULX GT1.5(2+1.5F) Mobile
+#define V_SA_PCI_DEV_2_GT2_SULXM_ID 0x0191E ///< Dev2-SKL ULX GT2 (2+2)Mobile
+#define V_SA_PCI_DEV_2_GT1_SSR_ID 0x0190A ///< Dev2-SKL GT1 (4+1F) Server
+#define V_SA_PCI_DEV_2_GT2_SSR_ID 0x0191A ///< Dev2-SKL GT2 (4/2+2) Server
+#define V_SA_PCI_DEV_2_GT3_SSR_ID 0x0192A ///< Dev2-SKL GT3 (2+3E) Server
+#define V_SA_PCI_DEV_2_GT4_SSR_ID 0x0193A ///< Dev2-SKL GT4 (4+4E) Server
+#define V_SA_PCI_DEV_2_GT1_SDT_ID 0x01902 ///< Dev2-SKL GT1 (2+1F) Desktop
+#define V_SA_PCI_DEV_2_GT2_SDT_ID 0x01912 ///< Dev2-SKL GT2 (4/2+2) Desktop
+#define V_SA_PCI_DEV_2_GT15_SDT_ID 0x01917 ///< Dev2-SKL GT1.5 (2+1.5F) Desktop
+#define V_SA_PCI_DEV_2_GT4_SDT_ID 0x01932 ///< Dev2-SKL GT4 (4+4E) Desktop
+///
+/// For KBL IGD
+///
+#define V_SA_PCI_DEV_2_GT1_KULTM_ID 0x05906 ///< Dev2-KBL ULT GT1 (2+1F) Mobile
+#define V_SA_PCI_DEV_2_GT15F_KULTM_ID 0x05913 ///< Dev2-KBL ULT GT1.5 (2+1.5F) Mobile
+#define V_SA_PCI_DEV_2_GT2_KULTM_ID 0x05916 ///< Dev2-KBL ULT GT2 (2+2) Mobile
+#define V_SA_PCI_DEV_2_GT2F_KULTM_ID 0x05921 ///< Dev2-KBL ULT GT2 (2+2F) Mobile
+#define V_SA_PCI_DEV_2_GT3_KULTM_ID 0x05926 ///< Dev2-KBL ULT GT3 (3+3/3E) Mobile
+#define V_SA_PCI_DEV_2_GT3E_KULTM_ID 0x05927 ///< Dev2-KBL ULT GT3 (2+3/3E) Mobile
+#define V_SA_PCI_DEV_2_GT1_KHALM_ID 0x0590B ///< Dev2-KBL Halo GT1 (2+1)
+#define V_SA_PCI_DEV_2_GT2_KHALM_ID 0x0591B ///< Dev2-KBL Halo GT2 (4/2+2)
+#define V_SA_PCI_DEV_2_GT3_KHALM_ID 0x0592B ///< Dev2-KBL Halo GT3 (4+3FE)
+#define V_SA_PCI_DEV_2_GT4_KHALM_ID 0x0593B ///< Dev2-KBL Halo GT4 (4+4E)
+#define V_SA_PCI_DEV_2_GT1_KULXM_ID 0x0590E ///< Dev2-KBL ULX GT1(2+1F) Mobile
+#define V_SA_PCI_DEV_2_GT15_KULXM_ID 0x05915 ///< Dev2-KBL ULX GT1.5(2+1.5F) Mobile
+#define V_SA_PCI_DEV_2_GT2_KULXM_ID 0x0591E ///< Dev2-KBL ULX GT2 (2+2)Mobile
+#define V_SA_PCI_DEV_2_GT1_KSR_ID 0x0590A ///< Dev2-KBL GT1 (4+1F) Server
+#define V_SA_PCI_DEV_2_GT2_KSR_ID 0x0591A ///< Dev2-KBL GT2 (4/2+2) Server
+#define V_SA_PCI_DEV_2_GT3_KSR_ID 0x0592A ///< Dev2-KBL GT3 (2+3E) Server
+#define V_SA_PCI_DEV_2_GT4_KSR_ID 0x0593A ///< Dev2-KBL GT4 (4+4E) Server
+#define V_SA_PCI_DEV_2_GT1_KDT_ID 0x05902 ///< Dev2-KBL GT1 (2+1F) Desktop
+#define V_SA_PCI_DEV_2_GT2_KDT_ID 0x05912 ///< Dev2-KBL GT2 (4/2+2) Desktop
+#define V_SA_PCI_DEV_2_GT15_KDT_ID 0x05917 ///< Dev2-KBL GT1.5 (2+1.5F) Desktop
+#define V_SA_PCI_DEV_2_GT4_KDT_ID 0x05932 ///< Dev2-KBL GT4 (4+4E) Desktop
+#define V_SA_PCI_DEV_2_GT2_KWKS_ID 0x0591D ///< Dev2-KBL GT2 (4+2) WorkStation
+#define V_SA_PCI_DEV_2_GT4_KWKS_ID 0x0593D ///< Dev2-KBL GT4 (4+4E) WorkStation
+///
+/// For CFL IGD
+///
+#define V_SA_PCI_DEV_2_GT2_CDT_ID 0x03E92 ///< Dev2-CFL GT2 (6+2) Desktop
+
+#define R_SA_IGD_VID 0x00
+#define R_SA_IGD_DID 0x02
+#define R_SA_IGD_CMD 0x04
+
+///
+/// GTTMMADR for SKL is 16MB alignment (Base address = [38:24])
+///
+#define R_SA_IGD_GTTMMADR 0x10
+#define R_SA_IGD_GMADR 0x18
+#define R_SA_IGD_IOBAR 0x20
+#define R_SA_IGD_BSM_OFFSET 0x005C ///< Base of Stolen Memory
+#define R_SA_IGD_MSAC_OFFSET 0x0062 ///< Multisize Aperture Control
+#define R_SA_IGD_SWSCI_OFFSET 0x00E8
+#define R_SA_IGD_ASLS_OFFSET 0x00FC ///< ASL Storage
+///
+/// Maximum number of SDRAM channels supported by the memory controller
+///
+///
+/// Maximum number of SDRAM channels supported by the memory controller
+///
+#define SA_MC_MAX_CHANNELS 2
+///
+/// Maximum number of DIMM sockets supported by each channel
+///
+#define SA_MC_MAX_SLOTS 2
+
+///
+/// Maximum number of sides supported per DIMM
+///
+#define SA_MC_MAX_SIDES 2
+
+///
+/// Maximum number of DIMM sockets supported by the memory controller
+///
+#define SA_MC_MAX_SOCKETS (SA_MC_MAX_CHANNELS * SA_MC_MAX_SLOTS)
+
+///
+/// Maximum number of rows supported by the memory controller
+///
+#define SA_MC_MAX_RANKS (SA_MC_MAX_SOCKETS * SA_MC_MAX_SIDES)
+
+///
+/// Maximum number of rows supported by the memory controller
+///
+#define SA_MC_MAX_ROWS (SA_MC_MAX_SIDES * SA_MC_MAX_SOCKETS)
+
+///
+/// Maximum memory supported by the memory controller
+/// 4 GB in terms of KB
+///
+#define SA_MC_MAX_MEM_CAPACITY (4 * 1024 * 1024)
+
+///
+/// Define the SPD Address for DIMM 0
+///
+#define SA_MC_DIMM0_SPD_ADDRESS 0xA0
+
+///
+/// Define the maximum number of data bytes on a system with no ECC memory support.
+///
+#define SA_MC_MAX_BYTES_NO_ECC (8)
+
+///
+/// Define the maximum number of SPD data bytes on a DIMM.
+///
+#define SA_MC_MAX_SPD_SIZE (512)
+
+///
+/// Vt-d Engine base address.
+///
+#define R_SA_MCHBAR_VTD1_OFFSET 0x5400 ///< HW UNIT2 for IGD
+#define R_SA_MCHBAR_VTD2_OFFSET 0x5410 ///< HW UNIT3 for all other - PEG, USB, SATA etc
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h
new file mode 100644
index 0000000000..02ec08fc96
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h
@@ -0,0 +1,107 @@
+/** @file
+ The GUID definition for SaConfigHob
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_CONFIG_HOB_H_
+#define _SA_CONFIG_HOB_H_
+
+#include <SaAccess.h>
+#include <Base.h>
+
+extern EFI_GUID gSaConfigHobGuid;
+
+#pragma pack (push,1)
+///
+/// DPR Directory Types
+///
+typedef enum {
+ EnumDprDirectoryTxt = 0,
+ EnumDprDirectoryBiosGuard
+} DPR_DIRECTORY_ELEMENT;
+
+#define DPR_DIRECTORY_TYPE_TXT 0x01
+#define DPR_DIRECTORY_TYPE_BIOSGUARD 0x02
+#define DPR_DIRECTORY_MAX 2
+#define SA_VTD_ENGINE_NUMBER 2
+
+///
+/// DPR directory entry definition
+///
+typedef struct {
+ UINT8 Type; ///< DPR Directory Type
+ UINT8 Size; ///< DPR Size in MB
+ UINT32 PhysBase; ///< Must be 4K aligned (bits 11..0 must be clear)
+ UINT16 Reserved; ///< Must be 0
+} DPR_DIRECTORY_ENTRY;
+
+///
+/// The data elements should be initialized by a Platform Module.
+/// The data structure is for VT-d driver initialization
+///
+typedef struct {
+ BOOLEAN VtdDisable; ///< 1 = Avoids programming Vtd bars, Vtd overrides and DMAR table
+ UINT32 BaseAddress[SA_VTD_ENGINE_NUMBER]; ///< This field is used to describe the base addresses for VT-d function
+ BOOLEAN X2ApicOptOut; ///< This field is used to enable the X2APIC_OPT_OUT bit in the DMAR table. <b>1=Enable/Set</b> and 0=Disable/Clear
+ BOOLEAN InterruptRemappingSupport; ///< This field is used to indicate Interrupt Remapping supported or not
+} SA_VTD_CONFIGURATION_HOB;
+
+///
+/// SA GPIO Data Structure
+///
+typedef struct {
+ UINT8 ExpanderNo; ///< =Expander No For I2C based GPIO
+ UINT32 GpioNo; ///< GPIO pad
+ BOOLEAN Active; ///< 0=Active Low; 1=Active High
+} SA_GPIO;
+
+///
+/// SA PCIE RTD3 GPIO Data Structure
+///
+typedef struct {
+ UINT8 GpioSupport; ///< 0=Not Supported; 1=PCH based; 2=I2C Based
+ SA_GPIO HoldRst; ///< Offset 8 This field contain PCIe HLD RESET GPIO value and level information
+ SA_GPIO PwrEnable; ///< This field contain PCIe PWR Enable GPIO value and level information
+ UINT32 WakeGpioNo; ///< This field contain PCIe RTD3 Device Wake GPIO number
+} PCIE_RTD3_GPIO;
+
+///
+/// SG Info HOB
+///
+typedef struct {
+ SG_MODE SgMode;
+ UINT8 RootPortDev;
+ UINT8 RootPortFun;
+ PCIE_RTD3_GPIO Rtd3Pcie0Gpio;
+ PCIE_RTD3_GPIO Rtd3Pcie1Gpio;
+ PCIE_RTD3_GPIO Rtd3Pcie2Gpio;
+ UINT16 DelayAfterPwrEn;
+ UINT16 DelayAfterHoldReset;
+} SA_RTD3;
+
+///
+/// System Agent Config Hob
+///
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID Hob type structure for gSaConfigHobGuid
+ DPR_DIRECTORY_ENTRY DprDirectory[DPR_DIRECTORY_MAX]; ///< DPR directory entry definition
+ BOOLEAN InitPcieAspmAfterOprom; ///< 1=initialize PCIe ASPM after Oprom; 0=before (This will be set basing on policy)
+ SA_RTD3 SaRtd3; ///< SG Info HOB
+ UINT8 ApertureSize; ///< Aperture size value
+ UINT8 ImguAcpiMode; ///< IMGU ACPI mode: 0=Disabled, 1=IGFX Child device, 2=ACPI device
+ SA_VTD_CONFIGURATION_HOB VtdData; ///< VT-d Data HOB
+ BOOLEAN CridEnable; ///< This field inidicates if CRID is enabled or disabled (to support Intel(R) SIPP)
+ BOOLEAN SkipPamLock; ///< 0=All PAM registers will be locked in System Agent code, 1=Do not lock PAM registers in System Agent code.
+ UINT8 PowerDownUnusedBundles[SA_PEG_MAX_FUN]; ///< PCIe power down unused bundles support
+ UINT8 PegMaxPayload[SA_PEG_MAX_FUN]; ///< PEG Max Pay Load Size (0xFF: Auto, 0:128B, 1:256B)
+} SA_CONFIG_HOB;
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
new file mode 100644
index 0000000000..4909ed8f62
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
@@ -0,0 +1,250 @@
+/** @file
+ This file provide services for DXE phase policy default initialization
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DxeSaPolicyLibrary.h"
+
+
+extern EFI_GUID gGraphicsDxeConfigGuid;
+extern EFI_GUID gMiscDxeConfigGuid;
+/**
+ This function prints the SA DXE phase policy.
+
+ @param[in] SaPolicy - SA DXE Policy protocol
+**/
+VOID
+SaPrintPolicyProtocol (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ MISC_DXE_CONFIG *MiscDxeConfig;
+
+ //
+ // Get requisite IP Config Blocks which needs to be used here
+ //
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gMiscDxeConfigGuid, (VOID *)&MiscDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG_CODE_BEGIN ();
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print BEGIN -----------------\n"));
+ DEBUG ((DEBUG_INFO, "Revision : %x\n", SaPolicy->TableHeader.Header.Revision));
+ ASSERT (SaPolicy->TableHeader.Header.Revision == SA_POLICY_PROTOCOL_REVISION);
+ DEBUG ((DEBUG_INFO, "------------------------ SA_MISC_CONFIGURATION -----------------\n"));
+ DEBUG ((DEBUG_INFO, " EnableAbove4GBMmio : %x\n", MiscDxeConfig->EnableAbove4GBMmio));
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print END -----------------\n"));
+ DEBUG_CODE_END ();
+
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+LoadIgdDxeDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+
+ GraphicsDxeConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "GraphicsDxeConfig->Header.GuidHob.Name = %g\n", &GraphicsDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "GraphicsDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", GraphicsDxeConfig->Header.GuidHob.Header.HobLength));
+ ///
+ /// Initialize the Graphics configuration
+ ///
+ GraphicsDxeConfig->VbtAddress = 0x00000000;
+ GraphicsDxeConfig->Size = 0;
+ GraphicsDxeConfig->PlatformConfig = 1;
+ GraphicsDxeConfig->AlsEnable = 2;
+ GraphicsDxeConfig->BacklightControlSupport = 2;
+ GraphicsDxeConfig->IgdBootType = 0;
+ GraphicsDxeConfig->IgdPanelType = 0;
+ GraphicsDxeConfig->IgdPanelScaling = 0;
+ GraphicsDxeConfig->IgdBlcConfig = 2;
+ GraphicsDxeConfig->LowPowerMode = 1;
+ GraphicsDxeConfig->IgdDvmtMemSize = 1;
+ GraphicsDxeConfig->GfxTurboIMON = 31;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+LoadMiscDxeDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ MISC_DXE_CONFIG *MiscDxeConfig;
+
+ MiscDxeConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "MiscDxeConfig->Header.GuidHob.Name = %g\n", &MiscDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "MiscDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", MiscDxeConfig->Header.GuidHob.Header.HobLength));
+ ///
+ /// RMRR Base and Limit Address for USB
+ ///
+ MiscDxeConfig->RmrrUsbBaseAddress = AllocateZeroPool (sizeof (EFI_PHYSICAL_ADDRESS) * 2);
+ ASSERT (MiscDxeConfig->RmrrUsbBaseAddress != NULL);
+ if (MiscDxeConfig->RmrrUsbBaseAddress != NULL) {
+ ///
+ /// BIOS must update USB RMRR base address
+ ///
+ MiscDxeConfig->RmrrUsbBaseAddress[0] = 0;
+ MiscDxeConfig->RmrrUsbBaseAddress[1] = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ LoadSaDxeConfigBlockDefault - Initialize default settings for each SA Config block
+
+ @param[in] ConfigBlockPointer The buffer pointer that will be initialized as specific config block
+ @param[in] BlockId Request to initialize defaults of specified config block by given Block ID
+
+ @retval EFI_SUCCESS The given buffer has contained the defaults of requested config block
+ @retval EFI_NOT_FOUND Block ID is not defined so no default Config block will be initialized
+**/
+EFI_STATUS
+EFIAPI
+LoadSaDxeConfigBlockDefault (
+ IN VOID *ConfigBlockPointer,
+ IN EFI_GUID BlockGuid
+ )
+{
+ if (CompareGuid (&BlockGuid, &gGraphicsDxeConfigGuid)) {
+ LoadIgdDxeDefault (ConfigBlockPointer);
+ } else if (CompareGuid (&BlockGuid, &gMiscDxeConfigGuid)) {
+ LoadMiscDxeDefault (ConfigBlockPointer);
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ CreateSaDxeConfigBlocks generates the config blocksg of SA DXE Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SaPolicy The pointer to get SA DXE Protocol instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreateSaDxeConfigBlocks (
+ IN OUT SA_POLICY_PROTOCOL **SaPolicy
+ )
+{
+ UINT16 TotalBlockSize;
+ UINT16 TotalBlockCount;
+ UINT16 BlockCount;
+ VOID *ConfigBlockPointer;
+ EFI_STATUS Status;
+ SA_POLICY_PROTOCOL *SaInitPolicy;
+ UINT16 RequiredSize;
+ STATIC CONFIG_BLOCK_HEADER SklSaDxeIpBlocks [] = {
+ {{{0, sizeof (GRAPHICS_DXE_CONFIG), 0}, {0}}, GRAPHICS_DXE_CONFIG_REVISION, 0, {0, 0}},
+ {{{0, sizeof (MISC_DXE_CONFIG), 0}, {0}}, MISC_DXE_CONFIG_REVISION, 0, {0, 0}}
+};
+
+ SaInitPolicy = NULL;
+ TotalBlockCount = sizeof (SklSaDxeIpBlocks) / sizeof (CONFIG_BLOCK_HEADER);
+ DEBUG ((DEBUG_INFO, "TotalBlockCount = 0x%x\n", TotalBlockCount));
+
+ TotalBlockSize = 0;
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ TotalBlockSize += (UINT32) SklSaDxeIpBlocks[BlockCount].GuidHob.Header.HobLength;
+ DEBUG ((DEBUG_INFO, "TotalBlockSize after adding Block[0x%x]= 0x%x\n", BlockCount, TotalBlockSize));
+ }
+
+ RequiredSize = sizeof (CONFIG_BLOCK_TABLE_HEADER) + TotalBlockSize;
+
+ Status = CreateConfigBlockTable (RequiredSize, (VOID *)&SaInitPolicy);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Initalize SklSaIpBlocks table GUID
+ //
+ CopyMem (&SklSaDxeIpBlocks[0].GuidHob.Name, &gGraphicsDxeConfigGuid, sizeof (EFI_GUID));
+ CopyMem (&SklSaDxeIpBlocks[1].GuidHob.Name, &gMiscDxeConfigGuid, sizeof (EFI_GUID));
+
+ //
+ // Initialize Policy Revision
+ //
+ SaInitPolicy->TableHeader.Header.Revision = SA_POLICY_PROTOCOL_REVISION;
+ //
+ // Initialize ConfigBlockPointer to NULL
+ //
+ ConfigBlockPointer = NULL;
+ //
+ // Loop to identify each config block from SklSaDxeIpBlocks[] Table and add each of them
+ //
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ ConfigBlockPointer = (VOID *)&SklSaDxeIpBlocks[BlockCount];
+ Status = AddConfigBlock ((VOID *) SaInitPolicy, (VOID *)&ConfigBlockPointer);
+ ASSERT_EFI_ERROR (Status);
+ LoadSaDxeConfigBlockDefault ((VOID *) ConfigBlockPointer, SklSaDxeIpBlocks[BlockCount].GuidHob.Name);
+ }
+ //
+ // Assignment for returning SaPolicy config block base address
+ //
+ *SaPolicy = SaInitPolicy;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ SaInstallPolicyProtocol installs SA Policy.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SaPolicy The pointer to SA Policy Protocol instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+SaInstallPolicyProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Print SA DXE Policy
+ ///
+ SaPrintPolicyProtocol (SaPolicy);
+
+ ///
+ /// Install protocol to to allow access to this Policy.
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gSaPolicyProtocolGuid,
+ SaPolicy,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
new file mode 100644
index 0000000000..f75ecb1388
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for the PeiSaPolicy library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeSaPolicyLib
+FILE_GUID = B402A3A4-4B82-410E-B79C-5914880A05E7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeSaPolicyLib
+
+
+[LibraryClasses]
+BaseMemoryLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+PciLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeSaPolicyLib.c
+DxeSaPolicyLibrary.h
+
+[Guids]
+gGraphicsDxeConfigGuid
+gMiscDxeConfigGuid
+[Protocols]
+gSaPolicyProtocolGuid ## PRODUCES \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
new file mode 100644
index 0000000000..f754072411
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
@@ -0,0 +1,26 @@
+/** @file
+ Header file for the DxeSaPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _DXE_SA_POLICY_LIBRARY_H_
+#define _DXE_SA_POLICY_LIBRARY_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ConfigBlockLib.h>
+
+#include <Protocol/SaPolicy.h>
+#endif // _DXE_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf
new file mode 100644
index 0000000000..860da17031
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for SA Platform Lib
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmSaPlatformLib
+FILE_GUID = 9DB5ACB4-DB23-43AE-A283-2ABEF365CBE0
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SaPlatformLib
+
+
+[LibraryClasses]
+BaseLib
+BaseMemoryLib
+DebugLib
+IoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+
+[Sources]
+SaPlatformLibrary.h
+SaPlatformLibrary.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c
new file mode 100644
index 0000000000..df662b0222
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c
@@ -0,0 +1,35 @@
+/** @file
+ SA Platform Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "SaPlatformLibrary.h"
+#include <Library/MmPciLib.h>
+#include <SaRegs.h>
+
+/**
+ Determine if PCH Link is DMI/OPI
+
+ @param[in] CpuModel CPU model
+
+ @retval TRUE DMI
+ @retval FALSE OPI
+**/
+BOOLEAN
+IsPchLinkDmi (
+ IN CPU_FAMILY CpuModel
+ )
+{
+ if (((CpuModel == EnumCpuSklDtHalo) || (CpuModel == EnumCpuKblDtHalo)) && ((MmioRead8 (MmPciBase (0, 0, 0) + R_SA_MC_DEVICE_ID) & (BIT2 | BIT1)) != BIT2)) {
+ return TRUE; // DMI
+ }
+ return FALSE; // OPI
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h
new file mode 100644
index 0000000000..632b801ad2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h
@@ -0,0 +1,27 @@
+/** @file
+ Header file for SA Platform Lib implementation.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SA_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+#define _SA_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <SaAccess.h>
+#include <CpuAccess.h>
+#include <Library/SaPlatformLib.h>
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.S b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.S
new file mode 100644
index 0000000000..d8fe66154a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.S
@@ -0,0 +1,58 @@
+## @file
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+ASM_GLOBAL ASM_PFX(SaMmioRead64)
+ASM_PFX(SaMmioRead64):
+ subl $16, %esp
+ movq %mm0, (%esp) #Save mm0 on stack
+ movl 20(%esp), %edx #edx = Address
+ movq (%edx), %mm0 #mm0 = [Address]
+ movq %mm0, 8(%esp) #Store mm0 on Stack
+ movq (%esp), %mm0 #Restore mm0
+ emms
+ movl 8(%esp), %eax #eax = [Address][31:0]
+ movl 12(%esp), %edx #edx = [Address][64:32]
+ addl $16, %esp
+ ret
+
+#-----------------------------------------------------------------------------
+#
+# Section: SaMmioWrite64
+#
+# Description: Write 64 bits to the Memory Mapped I/O space.
+# Use MMX instruction for atomic access, because some MC registers have side effect.
+#
+# @param[in] Address - Memory mapped I/O address.
+# @param[in] Value - The value to write.
+#
+#-----------------------------------------------------------------------------
+
+#UINT64
+#SaMmioWrite64 (
+# IN UINTN Address,
+# IN UINT64 Value
+# )
+
+ASM_GLOBAL ASM_PFX(SaMmioWrite64)
+ASM_PFX(SaMmioWrite64):
+ subl $8, %esp
+ movq %mm0, (%esp) #Save mm0 on Stack
+ movl 12(%esp), %edx #edx = Address
+ movq 16(%esp), %mm0 #mm0 = Value
+ movq %mm0, (%edx) #[Address] = Value
+ movq (%esp), %mm0 #Restore mm0
+ emms
+ movl 16(%esp), %eax #eax = Value[31:0]
+ movl 20(%esp), %edx #edx = Value[64:32]
+ addl $8, %esp
+ ret
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.asm b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.asm
new file mode 100644
index 0000000000..bef8aafe1a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.asm
@@ -0,0 +1,85 @@
+;; @file
+; This file provides assembly 64-bit atomic reads/writes required for memory initialization.
+;
+; Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials are licensed and made available under
+; the terms and conditions of the BSD License that accompanies this distribution.
+; The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;;
+
+.686p
+.xmm
+.model small, c
+
+.CODE
+
+;-----------------------------------------------------------------------------
+;
+; Section: SaMmioRead64
+;
+; Description: Read 64 bits from the Memory Mapped I/O space.
+; Use MMX instruction for atomic access, because some MC registers have side effect.
+;
+; @param[in] Address - Memory mapped I/O address.
+;
+;-----------------------------------------------------------------------------
+
+;UINT64
+;SaMmioRead64 (
+; IN UINTN Address
+; )
+
+SaMmioRead64 PROC NEAR PUBLIC
+ sub esp, 16
+ movq [esp], mm0 ;Save mm0 on stack
+ mov edx, [esp + 20] ;edx = Address
+ movq mm0, [edx] ;mm0 = [Address]
+ movq [esp + 8], mm0 ;Store mm0 on Stack
+ movq mm0, [esp] ;Restore mm0
+ emms
+ mov eax, [esp + 8] ;eax = [Address][31:0]
+ mov edx, [esp + 12] ;edx = [Address][64:32]
+ add esp, 16
+ ret
+SaMmioRead64 ENDP
+
+;-----------------------------------------------------------------------------
+;
+; Section: SaMmioWrite64
+;
+; Description: Write 64 bits to the Memory Mapped I/O space.
+; Use MMX instruction for atomic access, because some MC registers have side effect.
+;
+; @param[in] Address - Memory mapped I/O address.
+; @param[in] Value - The value to write.
+;
+;-----------------------------------------------------------------------------
+
+;UINT64
+;SaMmioWrite64 (
+; IN UINTN Address,
+; IN UINT64 Value
+; )
+
+SaMmioWrite64 PROC NEAR PUBLIC
+ sub esp, 8
+ movq [esp], mm0 ;Save mm0 on Stack
+ mov edx, [esp + 12] ;edx = Address
+ movq mm0, [esp + 16] ;mm0 = Value
+ movq [edx], mm0 ;[Address] = Value
+ movq mm0, [esp] ;Restore mm0
+ emms
+ mov eax, [esp + 16] ;eax = Value[31:0]
+ mov edx, [esp + 20] ;edx = Value[64:32]
+ add esp, 8
+ ret
+SaMmioWrite64 ENDP
+
+end
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.nasm b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.nasm
new file mode 100644
index 0000000000..5bc17065bd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/Ia32/MrcOemPlatform.nasm
@@ -0,0 +1,79 @@
+;; @file
+; This file provides assembly 64-bit atomic reads/writes required for memory initialization.
+;
+; Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials are licensed and made available under
+; the terms and conditions of the BSD License that accompanies this distribution.
+; The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;;
+
+
+SECTION .TEXT
+
+;-----------------------------------------------------------------------------
+;
+; Section: SaMmioRead64
+;
+; Description: Read 64 bits from the Memory Mapped I/O space.
+; Use MMX instruction for atomic access, because some MC registers have side effect.
+;
+; @param[in] Address - Memory mapped I/O address.
+;
+;-----------------------------------------------------------------------------
+
+;UINT64
+;SaMmioRead64 (
+; IN UINTN Address
+; )
+
+global ASM_PFX(SaMmioRead64)
+ASM_PFX(SaMmioRead64):
+ sub esp, 16
+ movq [esp], mm0 ;Save mm0 on stack
+ mov edx, [esp + 20] ;edx = Address
+ movq mm0, [edx] ;mm0 = [Address]
+ movq [esp + 8], mm0 ;Store mm0 on Stack
+ movq mm0, [esp] ;Restore mm0
+ emms
+ mov eax, [esp + 8] ;eax = [Address][31:0]
+ mov edx, [esp + 12] ;edx = [Address][64:32]
+ add esp, 16
+ ret
+
+;-----------------------------------------------------------------------------
+;
+; Section: SaMmioWrite64
+;
+; Description: Write 64 bits to the Memory Mapped I/O space.
+; Use MMX instruction for atomic access, because some MC registers have side effect.
+;
+; @param[in] Address - Memory mapped I/O address.
+; @param[in] Value - The value to write.
+;
+;-----------------------------------------------------------------------------
+
+;UINT64
+;SaMmioWrite64 (
+; IN UINTN Address,
+; IN UINT64 Value
+; )
+
+global ASM_PFX(SaMmioWrite64)
+ASM_PFX(SaMmioWrite64):
+ sub esp, 8
+ movq [esp], mm0 ;Save mm0 on Stack
+ mov edx, [esp + 12] ;edx = Address
+ movq mm0, [esp + 16] ;mm0 = Value
+ movq [edx], mm0 ;[Address] = Value
+ movq mm0, [esp] ;Restore mm0
+ emms
+ mov eax, [esp + 16] ;eax = Value[31:0]
+ mov edx, [esp + 20] ;edx = Value[64:32]
+ add esp, 8
+ ret
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.c
new file mode 100644
index 0000000000..e4d6f1b35c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.c
@@ -0,0 +1,747 @@
+/** @file
+ This file is SampleCode for Intel SA PEI Policy initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "MrcOemPlatform.h"
+#include <Library/CpuPlatformLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmbusLib.h>
+#include <PchAccess.h>
+#include <Library/PeiSaPolicyLib.h>
+#include <Library/PchCycleDecodingLib.h>
+
+#pragma pack (push, 1)
+typedef union {
+ struct {
+ UINT32 : 8;
+ UINT32 MAX_NON_TURBO_LIM_RATIO : 8;
+ UINT32 : 16;
+ UINT32 : 32;
+ } Bits;
+ UINT64 Data;
+ UINT32 Data32[2];
+ UINT16 Data16[4];
+ UINT8 Data8[8];
+} PCU_CR_PLATFORM_INFO_STRUCT;
+
+#pragma pack (pop)
+
+#define SA_SYSTEM_BCLK (100)
+#define PCU_CR_PLATFORM_INFO (0xCE)
+#define MRC_POST_CODE_LOW_BYTE_ADDR (0x48)
+#define MRC_POST_CODE_HIGH_BYTE_ADDR (0x49)
+#define MAX_SPD_PAGE_COUNT (2)
+#define MAX_SPD_PAGE_SIZE (256)
+#define MAX_SPD_DDR3_SIZE (MAX_SPD_PAGE_SIZE * 1)
+#define MAX_SPD_DDR4_SIZE (MAX_SPD_PAGE_SIZE * 2)
+#define MAX_SPD_SIZE (MAX_SPD_PAGE_SIZE * MAX_SPD_PAGE_COUNT)
+#define SPD_PAGE_ADDRESS_0 (0x6C)
+#define SPD_PAGE_ADDRESS_1 (0x6E)
+#define SPD_DDR3_XMP_OFFSET (176)
+#define SPD_DDR4_XMP_OFFSET (384)
+#define SPD_DDR3_SDRAM_TYPE_OFFSET (0x02)
+#define SPD_DDR3_SDRAM_TYPE_NUMBER (0x0B)
+#define SPD_DDR4_SDRAM_TYPE_NUMBER (0x0C)
+#define SPD_LPDDR3_SDRAM_TYPE_NUMBER (0xF1)
+#define SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER (0x0F)
+
+/**
+ Read the SPD data over the SMBus, at the specified SPD address, starting at
+ the specified starting offset and read the given amount of data.
+
+ @param[in] SpdAddress - SPD SMBUS address
+ @param[in, out] Buffer - Buffer to store the data.
+ @param[in] Start - Starting SPD offset
+ @param[in] Size - The number of bytes of data to read and also the size of the buffer.
+ @param[in, out] Page - The final page that is being pointed to.
+
+ @retval RETURN_SUCCESS if the read is successful, otherwise error status.
+**/
+static
+RETURN_STATUS
+DoSpdRead (
+ IN const UINT8 SpdAddress,
+ IN OUT UINT8 *const Buffer,
+ IN const UINT16 Start,
+ IN UINT16 Size,
+ IN OUT UINT8 *const Page
+ )
+{
+ RETURN_STATUS EfiStatus;
+ BOOLEAN PageUpdate;
+ UINT16 Count;
+ UINT16 Index;
+
+ EfiStatus = RETURN_DEVICE_ERROR;
+ if ((Buffer != NULL) && (Start < MAX_SPD_SIZE) && ((Start + Size) < MAX_SPD_SIZE)) {
+ Count = 0;
+ PageUpdate = FALSE;
+ while (Size--) {
+ Index = Start + Count;
+ if ((Index / MAX_SPD_PAGE_SIZE) != *Page) {
+ *Page = (UINT8) (Index / MAX_SPD_PAGE_SIZE);
+ PageUpdate = TRUE;
+ }
+ Index %= MAX_SPD_PAGE_SIZE;
+ if (PageUpdate == TRUE) {
+ PageUpdate = FALSE;
+ SmBusWriteDataByte ((*Page == 0) ? SPD_PAGE_ADDRESS_0 : SPD_PAGE_ADDRESS_1, 0, &EfiStatus);
+ }
+ Buffer[Count] = SmBusReadDataByte (SpdAddress | ((UINT32) Index << 8), &EfiStatus);
+ if (RETURN_SUCCESS != EfiStatus) {
+ Buffer[Count] = 0;
+ break;
+ }
+ Count++;
+ }
+ EfiStatus = RETURN_SUCCESS;
+ }
+ return (EfiStatus);
+}
+
+/**
+ See if there is valid XMP SPD data.
+
+ @param[in] Debug - Mrc debug structure.
+ @param[in, out] Spd - Mrc SPD structure.
+ @param[in] XmpStart - The current offset in the SPD.
+
+ @retval TRUE if valid, FALSE in not.
+**/
+static
+BOOLEAN
+VerifyXmp (
+ IN OUT MrcSpd *const Spd,
+ IN const UINT16 XmpStart
+ )
+{
+ SPD_EXTREME_MEMORY_PROFILE_HEADER *Header1;
+ SPD_EXTREME_MEMORY_PROFILE_HEADER_2_0 *Header2;
+ BOOLEAN Xmp;
+
+ Xmp = FALSE;
+
+ switch (((UINT8 *) Spd) [2]) {
+ case SPD_DDR3_SDRAM_TYPE_NUMBER:
+ Header1 = &Spd->Ddr3.Xmp.Header;
+ if (XmpStart == ((UINT32) (Header1) - (UINT32) Spd)) {
+ Xmp = TRUE;
+ if ((Header1->XmpRevision.Data & 0xFE) == 0x12) {
+ return (TRUE);
+ } else {
+ Header1->XmpId = 0;
+ Header1->XmpOrgConf.Data = 0;
+ Header1->XmpRevision.Data = 0;
+ }
+ }
+ break;
+ case SPD_DDR4_SDRAM_TYPE_NUMBER:
+ Header2 = &Spd->Ddr4.EndUser.Xmp.Header;
+ if (XmpStart == ((UINT32) (Header2) - (UINT32) Spd)) {
+ Xmp = TRUE;
+ if ((Header2->XmpRevision.Data) == 0x20) {
+ return (TRUE);
+ } else {
+ Header2->XmpId = 0;
+ Header2->XmpOrgConf.Data = 0;
+ Header2->XmpRevision.Data = 0;
+ }
+ }
+ break;
+ case SPD_LPDDR3_SDRAM_TYPE_NUMBER:
+ case SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER:
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+ if (!Xmp) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Read the SPD data over the SMBus, at the given SmBus SPD address and copy the data to the data structure.
+ The SPD data locations read is controlled by the current boot mode.
+
+ @param[in] BootMode - The current MRC boot mode.
+ @param[in] Address - SPD SmBus address offset.
+ @param[in] Buffer - Buffer that contains the data read from the SPD.
+ @param[in] SpdDdr3Table - Indicates which SPD bytes to read.
+ @param[in] SpdDdr3TableSize - Size of SpdDdr3Table in bytes.
+ @param[in] SpdDdr4Table - Indicates which SPD bytes to read.
+ @param[in] SpdDdr4TableSize - Size of SpdDdr4Table in bytes.
+ @param[in] SpdLpddrTable - Indicates which SPD bytes to read.
+ @param[in] SpdLpddrTableSize - Size of SpdLpddrTable in bytes.
+
+ @retval TRUE if the read is successful, otherwise FALSE on error.
+**/
+BOOLEAN
+GetSpdData (
+ IN SPD_BOOT_MODE BootMode,
+ IN UINT8 Address,
+ IN OUT UINT8 *Buffer,
+ IN UINT8 *SpdDdr3Table,
+ IN UINT32 SpdDdr3TableSize,
+ IN UINT8 *SpdDdr4Table,
+ IN UINT32 SpdDdr4TableSize,
+ IN UINT8 *SpdLpddrTable,
+ IN UINT32 SpdLpddrTableSize
+ )
+{
+ const SPD_OFFSET_TABLE *Tbl;
+ const SPD_OFFSET_TABLE *TableSelect;
+ RETURN_STATUS Status;
+ UINT32 Byte;
+ UINT32 Stop;
+ UINT8 Page;
+
+ Page = (UINT8) (~0);
+ Status = DoSpdRead (Address, &Buffer[SPD_DDR3_SDRAM_TYPE_OFFSET], 2, 1, &Page);
+ if (RETURN_SUCCESS == Status) {
+ switch (Buffer[SPD_DDR3_SDRAM_TYPE_OFFSET]) {
+ case SPD_DDR3_SDRAM_TYPE_NUMBER:
+ case SPD_LPDDR3_SDRAM_TYPE_NUMBER:
+ default:
+ TableSelect = (SPD_OFFSET_TABLE *) SpdDdr3Table;
+ Stop = (SpdDdr3TableSize / sizeof (SPD_OFFSET_TABLE));
+ break;
+ case SPD_DDR4_SDRAM_TYPE_NUMBER:
+ TableSelect = (SPD_OFFSET_TABLE *) SpdDdr4Table;
+ Stop = (SpdDdr4TableSize / sizeof (SPD_OFFSET_TABLE));
+ break;
+ case SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER:
+ TableSelect = (SPD_OFFSET_TABLE *) SpdLpddrTable;
+ Stop = (SpdLpddrTableSize / sizeof (SPD_OFFSET_TABLE));
+ break;
+ }
+ for (Byte = 0; (RETURN_SUCCESS == Status) && (Byte < Stop); Byte++) {
+ Tbl = &TableSelect[Byte];
+ if ((1 << BootMode) & Tbl->BootMode) {
+ Status = DoSpdRead (Address, &Buffer[Tbl->Start], Tbl->Start, Tbl->End - Tbl->Start + 1, &Page);
+ if (Status == RETURN_SUCCESS) {
+ if (SpdCold == BootMode) {
+ if (FALSE == VerifyXmp ((MrcSpd *) Buffer, Tbl->Start)) {
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ return ((RETURN_SUCCESS == Status) ? TRUE : FALSE);
+}
+
+//
+// This is from MdeModulePkg\Include\Guid\StatusCodeDataTypeDebug.h
+// Might need to be adjusted for a particular BIOS core
+//
+#ifndef EFI_STATUS_CODE_DATA_MAX_SIZE
+#define EFI_STATUS_CODE_DATA_MAX_SIZE 200
+#endif
+
+/**
+ Output a string to the debug stream/device.
+ If there is a '%' sign in the string, convert it to '%%', so that DEBUG() macro will print it properly.
+
+ @param[in] String - The string to output.
+
+ @retval Nothing.
+**/
+VOID
+SaDebugPrint (
+ VOID *String
+ )
+{
+ CHAR8 Str[EFI_STATUS_CODE_DATA_MAX_SIZE];
+ CHAR8 *InputStr;
+ CHAR8 *OutputStr;
+ UINT32 i;
+
+ InputStr = (CHAR8 *) String;
+ OutputStr = Str;
+ i = 0;
+ while (*InputStr != 0) {
+ if (i < (EFI_STATUS_CODE_DATA_MAX_SIZE - 2)) {
+ *OutputStr++ = *InputStr;
+ i++;
+ if (*InputStr++ == '%') {
+ *OutputStr++ = '%';
+ i++;
+ }
+ }
+ }
+ *OutputStr = 0; // Terminating NULL
+ DEBUG ((DEBUG_ERROR, Str));
+ return;
+}
+
+/**
+ Calculate the PCI device address for the given Bus/Device/Function/Offset.
+
+ @param[in] Bus - PCI bus
+ @param[in] Device - PCI device
+ @param[in] Function - PCI function
+ @param[in] Offset - Offset
+
+ @retval The PCI device address.
+**/
+UINT32
+GetPciDeviceAddress (
+ IN const UINT8 Bus,
+ IN const UINT8 Device,
+ IN const UINT8 Function,
+ IN const UINT8 Offset
+ )
+{
+ return (
+ ((UINT32) ((Bus) & 0xFF) << 16) |
+ ((UINT32) ((Device) & 0x1F) << 11) |
+ ((UINT32) ((Function) & 0x07) << 8) |
+ ((UINT32) ((Offset) & 0xFF) << 0) |
+ (1UL << 31));
+}
+
+/**
+ Calculate the PCIE device address for the given Bus/Device/Function/Offset.
+
+ @param[in] Bus - PCI bus
+ @param[in] Device - PCI device
+ @param[in] Function - PCI function
+ @param[in] Offset - Offset
+
+ The PCIE device address.
+
+ @retval The PCIe device address
+**/
+UINT32
+GetPcieDeviceAddress (
+ IN const UINT8 Bus,
+ IN const UINT8 Device,
+ IN const UINT8 Function,
+ IN const UINT8 Offset
+ )
+{
+ return (
+ ((UINT32) Bus << 20) +
+ ((UINT32) Device << 15) +
+ ((UINT32) Function << 12) +
+ ((UINT32) Offset << 0));
+}
+
+/**
+ Read specific RTC/CMOS RAM
+
+ @param[in] Location Point to RTC/CMOS RAM offset for read
+
+ @retval The data of specific location in RTC/CMOS RAM.
+**/
+UINT8
+PeiRtcRead (
+ IN const UINT8 Location
+ )
+{
+ UINT8 RtcIndexPort;
+ UINT8 RtcDataPort;
+
+ //
+ // CMOS access registers (using alternative access not to handle NMI bit)
+ //
+ if (Location < RTC_BANK_SIZE) {
+ //
+ // First bank
+ //
+ RtcIndexPort = R_PCH_RTC_INDEX_ALT;
+ RtcDataPort = R_PCH_RTC_TARGET_ALT;
+ } else {
+ //
+ // Second bank
+ //
+ RtcIndexPort = R_PCH_RTC_EXT_INDEX_ALT;
+ RtcDataPort = R_PCH_RTC_EXT_TARGET_ALT;
+ }
+
+ IoWrite8 (RtcIndexPort, Location & RTC_INDEX_MASK);
+ return IoRead8 (RtcDataPort);
+}
+
+/**
+ Returns the current time, as determined by reading the Real Time Clock (RTC) on the platform.
+ Since RTC time is stored in BCD, convert each value to binary.
+
+ @param[out] Seconds - The current second (0-59).
+ @param[out] Minutes - The current minute (0-59).
+ @param[out] Hours - The current hour (0-23).
+ @param[out] DayOfMonth - The current day of the month (1-31).
+ @param[out] Month - The current month (1-12).
+ @param[out] Year - The current year (2000-2099).
+
+ @retval Nothing.
+**/
+VOID
+GetRtcTime (
+ OUT UINT8 *const Seconds,
+ OUT UINT8 *const Minutes,
+ OUT UINT8 *const Hours,
+ OUT UINT8 *const DayOfMonth,
+ OUT UINT8 *const Month,
+ OUT UINT16 *const Year
+ )
+{
+ UINT32 Timeout;
+
+ //
+ // Wait until RTC "update in progress" bit goes low.
+ //
+ Timeout = 0x0FFFFF;
+ do {
+ IoWrite8 (RTC_INDEX_REGISTER, CMOS_REGA);
+ if ((IoRead8 (RTC_TARGET_REGISTER) & RTC_UPDATE_IN_PROGRESS) != RTC_UPDATE_IN_PROGRESS) {
+ break;
+ }
+ } while (--Timeout > 0);
+
+ if (0 == Timeout) {
+ IoWrite8 (RTC_INDEX_REGISTER, CMOS_REGB);
+ IoWrite8 (RTC_TARGET_REGISTER, RTC_HOLD | RTC_MODE_24HOUR);
+
+ IoWrite8 (RTC_INDEX_REGISTER, CMOS_REGA);
+ IoWrite8 (RTC_TARGET_REGISTER, RTC_CLOCK_DIVIDER | RTC_RATE_SELECT);
+
+ IoWrite8 (RTC_INDEX_REGISTER, CMOS_REGC);
+ IoRead8 (RTC_TARGET_REGISTER);
+
+ IoWrite8 (RTC_INDEX_REGISTER, CMOS_REGD);
+ IoRead8 (RTC_TARGET_REGISTER);
+
+ IoWrite8 (RTC_INDEX_REGISTER, CMOS_REGB);
+ IoWrite8 (RTC_TARGET_REGISTER, RTC_MODE_24HOUR);
+ }
+ //
+ // Read seconds
+ //
+ IoWrite8 (RTC_INDEX_REGISTER, RTC_SECONDS);
+ *Seconds = IoRead8 (RTC_TARGET_REGISTER);
+
+ //
+ // Read minutes
+ //
+ IoWrite8 (RTC_INDEX_REGISTER, RTC_MINUTES);
+ *Minutes = IoRead8 (RTC_TARGET_REGISTER);
+
+ //
+ // Read hours
+ //
+ IoWrite8 (RTC_INDEX_REGISTER, RTC_HOURS);
+ *Hours = IoRead8 (RTC_TARGET_REGISTER);
+
+ //
+ // Read day of month
+ //
+ IoWrite8 (RTC_INDEX_REGISTER, RTC_DAY_OF_MONTH);
+ *DayOfMonth = IoRead8 (RTC_TARGET_REGISTER);
+
+ //
+ // Read month
+ //
+ IoWrite8 (RTC_INDEX_REGISTER, RTC_MONTH);
+ *Month = IoRead8 (RTC_TARGET_REGISTER);
+
+ //
+ // Read year and add current century.
+ //
+ IoWrite8 (RTC_INDEX_REGISTER, RTC_YEAR);
+ *Year = IoRead8 (RTC_TARGET_REGISTER);
+
+ *Seconds = BCD2BINARY (*Seconds);
+ *Minutes = BCD2BINARY (*Minutes);
+ *Hours = BCD2BINARY (*Hours);
+ *DayOfMonth = BCD2BINARY (*DayOfMonth);
+ *Month = BCD2BINARY (*Month);
+ *Year = BCD2BINARY (*Year) + CENTURY_OFFSET;
+}
+
+/**
+ Gets CPU current time.
+
+ @param[in] GlobalData - Pointer to global MRC data struct.
+
+ @retval The current CPU time in milliseconds.
+**/
+UINT64
+GetCpuTime (
+ IN VOID *GlobalData
+ )
+{
+ MrcParameters *MrcData;
+ MrcInput *Inputs;
+ PCU_CR_PLATFORM_INFO_STRUCT Msr;
+ UINT32 TimeBase;
+
+ MrcData = (MrcParameters *) GlobalData;
+ Inputs = &MrcData->Inputs;
+
+ Msr.Data = AsmReadMsr64 (PCU_CR_PLATFORM_INFO);
+ TimeBase = (Inputs->BClkFrequency / 1000) * Msr.Bits.MAX_NON_TURBO_LIM_RATIO; //In Millisec
+ return ((TimeBase == 0) ? 0 : DivU64x32 (AsmReadTsc (), TimeBase));
+}
+
+/**
+ Sets the specified number of memory words, a word at a time, at the
+ specified destination.
+
+ @param[in, out] Dest - Destination pointer.
+ @param[in] NumWords - The number of dwords to set.
+ @param[in] Value - The value to set.
+
+ @retval Pointer to the buffer.
+**/
+VOID *
+SetMemWord (
+ IN OUT VOID *Dest,
+ IN UINTN NumWords,
+ IN const UINT16 Value
+ )
+{
+ UINT16 *Buffer;
+
+ Buffer = (UINT16 *) Dest;
+ while (0 != NumWords--) {
+ *Buffer++ = Value;
+ }
+
+ return (Dest);
+}
+
+/**
+ Sets the specified number of memory dwords, a dword at a time, at the
+ specified destination.
+
+ @param[in, out] Dest - Destination pointer.
+ @param[in] NumDwords - The number of dwords to set.
+ @param[in] Value - The value to set.
+
+ @retval Pointer to the buffer.
+**/
+VOID *
+SetMemDword (
+ IN OUT VOID *Dest,
+ IN UINT32 NumDwords,
+ IN const UINT32 Value
+ )
+{
+ UINT32 *Buffer;
+
+ Buffer = (UINT32 *) Dest;
+ while (0 != NumDwords--) {
+ *Buffer++ = Value;
+ }
+
+ return (Dest);
+}
+
+
+/**
+ Gets the current memory voltage (VDD).
+
+ @param[in] GlobalData - Pointer to global MRC data struct.
+ @param[in] DefaultVdd - Default Vdd for the given platform.
+
+ @retval The current memory voltage (VDD), in millivolts. 0 means platform default.
+**/
+UINT32
+GetMemoryVdd (
+ IN VOID *GlobalData,
+ IN UINT32 DefaultVdd
+ )
+{
+ MrcParameters *MrcData;
+ UINT32 CurrentVoltage;
+
+ MrcData = (MrcParameters *) GlobalData;
+ CurrentVoltage = DefaultVdd;
+
+ return CurrentVoltage;
+}
+
+/**
+ Sets the memory voltage (VDD) to the specified value.
+
+ @param[in] GlobalData - Pointer to global MRC data struct.
+ @param[in] DefaultVdd - Default Vdd for the given platform.
+ @param[in] Voltage - The new memory voltage to set.
+
+ @retval The actual memory voltage (VDD), in millivolts, that is closest to what the caller passed in.
+**/
+UINT32
+SetMemoryVdd (
+ IN VOID *GlobalData,
+ IN UINT32 DefaultVdd,
+ IN UINT32 Voltage
+ )
+{
+ MrcParameters *MrcData;
+
+ MrcData = (MrcParameters *) GlobalData;
+
+ return Voltage;
+}
+
+/**
+ This function is used by the OEM to do a dedicated task during the MRC.
+
+ @param[in] GlobalData - include all the MRC data
+ @param[in] OemStatusCommand - A command that indicates the task to perform.
+ @param[in] Pointer - general ptr for general use.
+
+ @retval The status of the task.
+**/
+MrcStatus
+CheckPoint (
+ IN VOID *GlobalData,
+ IN MrcOemStatusCommand OemStatusCommand,
+ IN VOID *Pointer
+ )
+{
+ const SA_MEMORY_FUNCTIONS *SaCall;
+ MrcParameters *MrcData;
+ MrcInput *Inputs;
+ MrcStatus Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
+ MEMORY_CONFIG_NO_CRC *MemConfigNoCrc;
+ EFI_STATUS Status1;
+
+ //
+ // Locate SiPreMemPolicyPpi to do a GetConfigBlock() to access platform data
+ //
+ Status1 = PeiServicesLocatePpi (
+ &gSiPreMemPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPreMemPolicyPpi
+ );
+ ASSERT_EFI_ERROR (Status1);
+
+ Status1 = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gMemoryConfigNoCrcGuid, (VOID *) &MemConfigNoCrc);
+ ASSERT_EFI_ERROR (Status1);
+ MrcData = (MrcParameters *) GlobalData;
+ Inputs = &MrcData->Inputs;
+ SiPreMemPolicyPpi = (SI_PREMEM_POLICY_PPI *) Inputs->SiPreMemPolicyPpi;
+ SaCall = &MemConfigNoCrc->MrcCall;
+ Status = mrcSuccess;
+
+ switch (OemStatusCommand) {
+ case OemAfterNormalMode:
+ SaCall->MrcThermalOverrides (MrcData);
+ break;
+
+ default:
+ break;
+ }
+
+ return (mrcSuccess);
+}
+
+/**
+ Typically used to display to the I/O port 80h.
+
+ @param[in] GlobalData - Mrc Global Data
+ @param[in] DisplayDebugNumber - the number to display on port 80.
+
+ @retval Nothing.
+**/
+VOID
+DebugHook (
+ IN VOID *GlobalData,
+ UINT16 DisplayDebugNumber
+ )
+{
+ MrcParameters *MrcData;
+ MrcOutput *Outputs;
+ MrcDebug *Debug;
+ EFI_STATUS Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
+ SA_MISC_PEI_PREMEM_CONFIG *MiscPeiPreMemConfig;
+
+ MrcData = (MrcParameters *) GlobalData;
+ Outputs = &MrcData->Outputs;
+ Debug = &Outputs->Debug;
+
+ Debug->PostCode[MRC_POST_CODE] = DisplayDebugNumber;
+ IoWrite16 (0x80, DisplayDebugNumber);
+ DEBUG ((DEBUG_INFO, "Post Code: %04Xh\n", DisplayDebugNumber));
+
+ //
+ // Locate SiPreMemPolicyPpi to do a GetConfigBlock() to access platform data
+ //
+ Status = PeiServicesLocatePpi (&gSiPreMemPolicyPpiGuid, 0, NULL, (VOID **) &SiPreMemPolicyPpi);
+ ASSERT_EFI_ERROR (Status);
+ if (Status == EFI_SUCCESS) {
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSaMiscPeiPreMemConfigGuid, (VOID *) &MiscPeiPreMemConfig);
+ }
+ return;
+}
+
+/**
+ Hook to take any action after returning from MrcStartMemoryConfiguration()
+ and prior to taking any action regarding MrcStatus. Pre-populated with issuing
+ Intel Silicon View Technology (ISVT) checkpoint 0x10.
+
+ @param[in] GlobalData - Mrc Global Data
+ @param[in] MrcStatus - Mrc status variable
+**/
+void
+ReturnFromSmc (
+ IN VOID *GlobalData,
+ IN UINT32 MrcStatus
+ )
+{
+ return;
+}
+
+/**
+ Assert or deassert DRAM_RESET# pin; this is used in JEDEC Reset.
+
+ @param[in] PciEBaseAddress - PCI express base address.
+ @param[in] ResetValue - desired value of DRAM_RESET#. 1 - reset deasserted, 0 - reset asserted.
+**/
+VOID
+SaDramReset (
+ IN UINT32 PciEBaseAddress,
+ IN UINT32 ResetValue
+ )
+{
+ UINT32 MmioBase;
+ UINT32 PmCfg2;
+
+ //
+ // Get the PCH PWRM Base
+ //
+ PchPwrmBaseGet (&MmioBase);
+
+ //
+ // Set DRAM RESET# value via PCH register (both SKL PCH-H and SKL PCH-LP)
+ //
+ PmCfg2 = MmioRead32 (MmioBase + R_PCH_PWRM_CFG2);
+ PmCfg2 &= ~(B_PCH_PWRM_CFG2_DRAM_RESET_CTL);
+ PmCfg2 |= (ResetValue << 26);
+ MmioWrite32 (MmioBase + R_PCH_PWRM_CFG2, PmCfg2);
+
+ return;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.h
new file mode 100644
index 0000000000..f561138b04
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/MrcOemPlatform.h
@@ -0,0 +1,313 @@
+/** @file
+ This file contains functions that read the SPD data for each DIMM slot over
+ the SMBus interface.
+ This file is SampleCode for Intel SA PEI Policy initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "PeiSaPolicyLibrary.h"
+#include "MrcInterface.h"
+#include <SaRegs.h>
+
+#define RTC_INDEX_REGISTER (0x70)
+#define RTC_TARGET_REGISTER (0x71)
+
+#define RTC_INDEX_MASK (0x7F)
+#define RTC_BANK_SIZE (0x80)
+
+#define RTC_SECONDS (0x00)
+#define RTC_MINUTES (0x02)
+#define RTC_HOURS (0x04)
+#define RTC_DAY_OF_MONTH (0x07)
+#define RTC_MONTH (0x08)
+#define RTC_YEAR (0x09)
+#define CMOS_REGA (0x0A)
+#define CMOS_REGB (0x0B)
+#define CMOS_REGC (0x0C)
+#define CMOS_REGD (0x0D)
+
+#define RTC_UPDATE_IN_PROGRESS (0x80)
+#define RTC_HOLD (0x80)
+#define RTC_MODE_24HOUR (0x02)
+#define RTC_CLOCK_DIVIDER (0x20)
+#define RTC_RATE_SELECT (0x06)
+
+#define BCD2BINARY(A) (((((A) >> 4) & 0xF) * 10) + ((A) & 0xF))
+#define CENTURY_OFFSET (2000)
+
+/**
+ Read the SPD data over the SMBus, at the given SmBus SPD address and copy the data to the data structure.
+ The SPD data locations read is controlled by the current boot mode.
+
+ @param[in] BootMode - The current MRC boot mode.
+ @param[in] Address - SPD SmBus address offset.
+ @param[in] Buffer - Buffer that contains the data read from the SPD.
+ @param[in] SpdDdr3Table - Indicates which SPD bytes to read.
+ @param[in] SpdDdr3TableSize - Size of SpdDdr3Table in bytes.
+ @param[in] SpdDdr4Table - Indicates which SPD bytes to read.
+ @param[in] SpdDdr4TableSize - Size of SpdDdr4Table in bytes.
+ @param[in] SpdLpddrTable - Indicates which SPD bytes to read.
+ @param[in] SpdLpddrTableSize - Size of SpdLpddrTable in bytes.
+
+ @retval TRUE if the read is successful, otherwise FALSE on error.
+**/
+BOOLEAN
+GetSpdData (
+ IN SPD_BOOT_MODE BootMode,
+ IN UINT8 Address,
+ IN OUT UINT8 *Buffer,
+ IN UINT8 *SpdDdr3Table,
+ IN UINT32 SpdDdr3TableSize,
+ IN UINT8 *SpdDdr4Table,
+ IN UINT32 SpdDdr4TableSize,
+ IN UINT8 *SpdLpddrTable,
+ IN UINT32 SpdLpddrTableSize
+ );
+
+/**
+ Output a string to the debug stream/device.
+
+ @param[in] String - The string to output.
+**/
+VOID
+SaDebugPrint (
+ VOID *String
+ );
+
+/**
+ Calculate the PCI device address for the given Bus/Device/Function/Offset.
+
+ @param[in] Bus - PCI bus
+ @param[in] Device - PCI device
+ @param[in] Function - PCI function
+ @param[in] Offset - Offset
+
+ @retval The PCI device address.
+**/
+UINT32
+GetPciDeviceAddress (
+ IN const UINT8 Bus,
+ IN const UINT8 Device,
+ IN const UINT8 Function,
+ IN const UINT8 Offset
+ );
+
+/**
+ Calculate the PCIE device address for the given Bus/Device/Function/Offset.
+
+ @param[in] Bus - PCI bus
+ @param[in] Device - PCI device
+ @param[in] Function - PCI function
+ @param[in] Offset - Offset
+
+ The PCIE device address.
+
+ @retval The PCIe device address
+**/
+UINT32
+GetPcieDeviceAddress (
+ IN const UINT8 Bus,
+ IN const UINT8 Device,
+ IN const UINT8 Function,
+ IN const UINT8 Offset
+ );
+
+/**
+ Read specific RTC/CMOS RAM
+
+ @param[in] Location Point to RTC/CMOS RAM offset for read
+
+ @retval The data of specific location in RTC/CMOS RAM.
+**/
+UINT8
+PeiRtcRead (
+ IN const UINT8 Location
+ );
+
+/**
+ Returns the current time, as determined by reading the Real Time Clock (RTC) on the platform.
+ Since RTC time is stored in BCD, convert each value to binary.
+
+ @param[out] Seconds - The current second (0-59).
+ @param[out] Minutes - The current minute (0-59).
+ @param[out] Hours - The current hour (0-23).
+ @param[out] DayOfMonth - The current day of the month (1-31).
+ @param[out] Month - The current month (1-12).
+ @param[out] Year - The current year (2000-2099).
+**/
+VOID
+GetRtcTime (
+ OUT UINT8 *const Seconds,
+ OUT UINT8 *const Minutes,
+ OUT UINT8 *const Hours,
+ OUT UINT8 *const DayOfMonth,
+ OUT UINT8 *const Month,
+ OUT UINT16 *const Year
+ );
+
+/**
+ Gets CPU current time.
+
+ @param[in] GlobalData - Pointer to global MRC data struct.
+
+ @retval The current CPU time in milliseconds.
+**/
+UINT64
+GetCpuTime (
+ IN VOID *GlobalData
+ );
+
+/**
+ Sets the specified number of memory words, a word at a time, at the
+ specified destination.
+
+ @param[in, out] Dest - Destination pointer.
+ @param[in] NumWords - The number of dwords to set.
+ @param[in] Value - The value to set.
+
+ @retval Pointer to the buffer.
+**/
+VOID *
+SetMemWord (
+ IN OUT VOID *Dest,
+ IN UINTN NumWords,
+ IN const UINT16 Value
+ );
+
+/**
+ Sets the specified number of memory dwords, a dword at a time, at the
+ specified destination.
+
+ @param[in, out] Dest - Destination pointer.
+ @param[in] NumDwords - The number of dwords to set.
+ @param[in] Value - The value to set.
+
+ @retval Pointer to the buffer.
+**/
+VOID *
+SetMemDword (
+ IN OUT VOID *Dest,
+ IN UINT32 NumDwords,
+ IN const UINT32 Value
+ );
+
+/**
+ Read 64 bits from the Memory Mapped I/O space.
+ Use MMX instruction for atomic access, because some MC registers have side effect.
+
+ @param[in] Address - Memory mapped I/O address.
+**/
+UINT64
+SaMmioRead64 (
+ IN UINTN Address
+ );
+
+/**
+ Write 64 bits to the Memory Mapped I/O space.
+ Use MMX instruction for atomic access, because some MC registers have side effect.
+
+ @param[in] Address - Memory mapped I/O address.
+ @param[in] Value - The value to write.
+**/
+UINT64
+SaMmioWrite64 (
+ IN UINTN Address,
+ IN UINT64 Value
+ );
+
+/**
+ Gets the current memory voltage (VDD).
+
+ @param[in] GlobalData - Pointer to global MRC data struct.
+ @param[in] DefaultVdd - Default Vdd for the given platform.
+
+ @retval The current memory voltage (VDD), in millivolts. 0 means platform default.
+**/
+UINT32
+GetMemoryVdd (
+ IN VOID *GlobalData,
+ IN UINT32 DefaultVdd
+ );
+
+/**
+ Sets the memory voltage (VDD) to the specified value.
+
+ @param[in] GlobalData - Pointer to global MRC data struct.
+ @param[in] DefaultVdd - Default Vdd for the given platform.
+ @param[in] Voltage - The new memory voltage to set.
+
+ @retval The actual memory voltage (VDD), in millivolts, that is closest to what the caller passed in.
+**/
+UINT32
+SetMemoryVdd (
+ IN VOID *GlobalData,
+ IN UINT32 DefaultVdd,
+ IN UINT32 Voltage
+ );
+
+/**
+ Check point that is called at various points in the MRC.
+
+ @param[in] GlobalData - MRC global data.
+ @param[in] Command - OEM command.
+ @param[in] Pointer - Command specific data.
+
+ @retval MrcStatus value.
+**/
+UINT32
+CheckPoint (
+ VOID *GlobalData,
+ UINT32 Command,
+ VOID *Pointer
+ );
+
+/**
+ Typically used to display to the I/O port 80h.
+
+ @param[in] GlobalData - Mrc Global Data
+ @param[in] DisplayDebugNumber - the number to display on port 80.
+
+ @retval Nothing.
+**/
+VOID
+DebugHook (
+ VOID *GlobalData,
+ UINT16 DisplayDebugNumber
+ );
+
+/**
+ Hook to take any action after returning from MrcStartMemoryConfiguration()
+ and prior to taking any action regarding MrcStatus. Pre-populated with issuing
+ Intel Silicon View Technology (ISVT) checkpoint 0x01.
+
+ @param[in] GlobalData - Mrc Global Data
+ @param[in] MrcStatus - Mrc status variable
+**/
+VOID
+ReturnFromSmc (
+ VOID *GlobalData,
+ UINT32 MrcStatus
+ );
+
+/**
+ Assert or deassert DRAM_RESET# pin; this is used in JEDEC Reset.
+
+ @param[in] PciEBaseAddress - PCI express base address.
+ @param[in] ResetValue - desired value of DRAM_RESET#. 1 - reset deasserted, 0 - reset asserted.
+**/
+VOID
+SaDramReset (
+ IN UINT32 PciEBaseAddress,
+ IN UINT32 ResetValue
+ );
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.c
new file mode 100644
index 0000000000..ddc83ba4b2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.c
@@ -0,0 +1,365 @@
+/** @file
+ This file provides services for PEI policy default initialization
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiSaPolicyLibrary.h"
+#include <Library/GpioLib.h>
+#include <GpioPinsSklH.h>
+#include <Library/CpuPlatformLib.h>
+#include <MrcTypes.h>
+#include "MrcInterface.h"
+
+
+extern EFI_GUID gSaMiscPeiPreMemConfigGuid;
+extern EFI_GUID gMemoryConfigGuid;
+extern EFI_GUID gMemoryConfigNoCrcGuid;
+extern EFI_GUID gGraphicsPeiConfigGuid;
+extern EFI_GUID gVtdConfigGuid;
+
+//
+// Function call to Load defaults for Individial IP Blocks
+//
+VOID
+LoadSaMiscPeiPreMemDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SA_MISC_PEI_PREMEM_CONFIG *MiscPeiPreMemConfig;
+
+ MiscPeiPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->Header.GuidHob.Name = %g\n", &MiscPeiPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", MiscPeiPreMemConfig->Header.GuidHob.Header.HobLength));
+}
+
+VOID
+LoadVtdDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ VTD_CONFIG *Vtd;
+
+ Vtd = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "Vtd->Header.GuidHob.Name = %g\n", &Vtd->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "Vtd->Header.GuidHob.Header.HobLength = 0x%x\n", Vtd->Header.GuidHob.Header.HobLength));
+
+ //
+ // Initialize the Vtd Configuration
+ //
+ Vtd->BaseAddress[0] = 0xFED90000;
+ Vtd->BaseAddress[1] = 0xFED91000;
+}
+
+VOID
+LoadGraphichsPeiDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ GRAPHICS_PEI_CONFIG *GtConfig;
+
+ GtConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "GtConfig->Header.GuidHob.Name = %g\n", &GtConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "GtConfig->Header.GuidHob.Header.HobLength = 0x%x\n", GtConfig->Header.GuidHob.Header.HobLength));
+}
+
+VOID
+LoadMemConfigNoCrcDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+
+ MEMORY_CONFIG_NO_CRC *MemConfigNoCrc;
+
+ MemConfigNoCrc = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "MemConfigNoCrc->Header.GuidHob.Name = %g\n", &MemConfigNoCrc->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "MemConfigNoCrc->Header.GuidHob.Header.HobLength = 0x%x\n", MemConfigNoCrc->Header.GuidHob.Header.HobLength));
+ //
+ // Allocating memory space for pointer structures inside MemConfigNoCrc
+ //
+ MemConfigNoCrc->SpdData = (SPD_DATA_BUFFER *) AllocateZeroPool (sizeof (SPD_DATA_BUFFER));
+ ASSERT (MemConfigNoCrc->SpdData != NULL);
+ if (MemConfigNoCrc->SpdData == NULL) {
+ return;
+ }
+
+ MemConfigNoCrc->DqByteMap = (SA_MEMORY_DQ_MAPPING *) AllocateZeroPool (sizeof (SA_MEMORY_DQ_MAPPING));
+ ASSERT (MemConfigNoCrc->DqByteMap != NULL);
+ if (MemConfigNoCrc->DqByteMap == NULL) {
+ return;
+ }
+
+ MemConfigNoCrc->DqsMap = (SA_MEMORY_DQS_MAPPING *) AllocateZeroPool (sizeof (SA_MEMORY_DQS_MAPPING));
+ ASSERT (MemConfigNoCrc->DqsMap != NULL);
+ if (MemConfigNoCrc->DqsMap == NULL) {
+ return;
+ }
+
+ MemConfigNoCrc->RcompData = (SA_MEMORY_RCOMP *) AllocateZeroPool (sizeof (SA_MEMORY_RCOMP));
+ ASSERT (MemConfigNoCrc->RcompData != NULL);
+ if (MemConfigNoCrc->RcompData == NULL) {
+ return;
+ }
+
+ //
+ // Set PlatformMemory Size
+ //
+ MemConfigNoCrc->PlatformMemorySize = PcdGet32 (PcdPeiMinMemorySize);
+
+ MemConfigNoCrc->SerialDebugLevel = 3; //< Enable MRC debug message
+
+}
+
+
+VOID
+LoadMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ MEMORY_CONFIGURATION *MemConfig;
+ CPU_SKU CpuSku;
+ UINT16 DeviceId;
+ BOOLEAN HasEdram;
+
+ CpuSku = GetCpuSku ();
+ DeviceId = MmioRead16 (MmPciBase (SA_MC_BUS, 0, 0) + R_SA_MC_DEVICE_ID);
+ HasEdram = ((AsmReadMsr64 (MSR_PLATFORM_INFO) & B_PLATFORM_INFO_EDRAM_EN) != 0);
+
+
+ MemConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "MemConfig->Header.GuidHob.Name = %g\n", &MemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "MemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", MemConfig->Header.GuidHob.Header.HobLength));
+ //
+ // Initialize the Memory Configuration
+ //
+ MemConfig->EccSupport = 1;
+ MemConfig->ScramblerSupport = 1;
+ MemConfig->PowerDownMode = 0xFF;
+ MemConfig->RankInterleave = TRUE;
+ MemConfig->EnhancedInterleave = TRUE;
+ MemConfig->CmdTriStateDis = 0;
+ MemConfig->EnCmdRate = 3;
+ MemConfig->AutoSelfRefreshSupport = TRUE;
+ MemConfig->ExtTemperatureSupport = TRUE;
+
+ //
+ // Thermal Management Configuration
+ //
+ MemConfig->ThermalManagement = 1;
+ //
+ // Channel Hash Configuration
+ //
+ MemConfig->ChHashEnable = TRUE;
+ MemConfig->ChHashMask = ((CpuSku == EnumCpuUlt) && (HasEdram)) ? 0x30D0 : 0x30C8;
+ MemConfig->ChHashInterleaveBit = 2;
+ //
+ // Options for Thermal settings
+ //
+ MemConfig->EnablePwrDn = 1;
+ MemConfig->EnablePwrDnLpddr = 1;
+ MemConfig->DdrThermalSensor = 1;
+
+ MemConfig->EnergyScaleFact = 3;
+ MemConfig->WarmThresholdCh0Dimm0 = 0xFF;
+ MemConfig->WarmThresholdCh0Dimm1 = 0xFF;
+ MemConfig->WarmThresholdCh1Dimm0 = 0xFF;
+ MemConfig->WarmThresholdCh1Dimm1 = 0xFF;
+ MemConfig->HotThresholdCh0Dimm0 = 0xFF;
+ MemConfig->HotThresholdCh0Dimm1 = 0xFF;
+ MemConfig->HotThresholdCh1Dimm0 = 0xFF;
+ MemConfig->HotThresholdCh1Dimm1 = 0xFF;
+ MemConfig->WarmBudgetCh0Dimm0 = 0xFF;
+ MemConfig->WarmBudgetCh0Dimm1 = 0xFF;
+ MemConfig->WarmBudgetCh1Dimm0 = 0xFF;
+ MemConfig->WarmBudgetCh1Dimm1 = 0xFF;
+ MemConfig->HotBudgetCh0Dimm0 = 0xFF;
+ MemConfig->HotBudgetCh0Dimm1 = 0xFF;
+ MemConfig->HotBudgetCh1Dimm0 = 0xFF;
+ MemConfig->HotBudgetCh1Dimm1 = 0xFF;
+
+ MemConfig->SrefCfgEna = 1;
+ MemConfig->SrefCfgIdleTmr = 0x200;
+ MemConfig->ThrtCkeMinTmr = 0x30;
+ MemConfig->ThrtCkeMinDefeatLpddr = 1;
+ MemConfig->ThrtCkeMinTmrLpddr = 0x40;
+
+ //
+ // CA Vref routing: board-dependent
+ // 0 - VREF_CA goes to both CH_A and CH_B (LPDDR3/DDR3L)
+ // 1 - VREF_CA to CH_A, VREF_DQ_A to CH_B (should not be used)
+ // 2 - VREF_CA to CH_A, VREF_DQ_B to CH_B (DDR4)
+ //
+ //MemConfig->CaVrefConfig = 0;
+
+ MemConfig->VttTermination = ((CpuSku == EnumCpuUlx) || (CpuSku == EnumCpuUlt));
+ MemConfig->VttCompForVsshi = 1;
+
+ MemConfig->McLock = TRUE;
+
+ MemConfig->GdxcIotSize = 4;
+ MemConfig->GdxcMotSize = 12;
+
+ //
+ // MRC training steps
+ //
+ MemConfig->ERDMPRTC2D = 1;
+ MemConfig->SOT = 1;
+ MemConfig->RDMPRT = 1;
+ MemConfig->RCVET = 1;
+ MemConfig->JWRL = 1;
+ MemConfig->EWRTC2D = 1;
+ MemConfig->ERDTC2D = 1;
+ MemConfig->WRTC1D = 1;
+ MemConfig->WRVC1D = 1;
+ MemConfig->RDTC1D = 1;
+ MemConfig->DIMMODTT = 1;
+ MemConfig->DIMMRONT = 1;
+ MemConfig->WRSRT = 1;
+ MemConfig->RDODTT = 1;
+ MemConfig->RDEQT = 1;
+ MemConfig->RDAPT = 1;
+ MemConfig->WRTC2D = 1;
+ MemConfig->RDTC2D = 1;
+ MemConfig->CMDVC = 1;
+ MemConfig->WRVC2D = 1;
+ MemConfig->RDVC2D = 1;
+ MemConfig->LCT = 1;
+ MemConfig->RTL = 1;
+ MemConfig->TAT = 1;
+ MemConfig->ALIASCHK = 1;
+ MemConfig->RCVENC1D = 1;
+ MemConfig->RMC = 1;
+ MemConfig->CMDSR = 1;
+ MemConfig->CMDDSEQ = 1;
+ MemConfig->CMDNORM = 1;
+ MemConfig->EWRDSEQ = 1;
+
+ // MrcFastBoot enabled by default
+ MemConfig->MrcFastBoot = TRUE;
+ MemConfig->RemapEnable = TRUE;
+ MemConfig->BClkFrequency = 100 * 1000 * 1000;
+
+ MemConfig->Vc1ReadMeter = TRUE;
+ MemConfig->Vc1ReadMeterTimeWindow = 0x320;
+ MemConfig->Vc1ReadMeterThreshold = 0x118;
+ MemConfig->StrongWkLeaker = 7;
+
+ MemConfig->MobilePlatform = (IS_SA_DEVICE_ID_MOBILE (DeviceId)) ? TRUE : FALSE;
+ MemConfig->PciIndex = 0xCF8;
+ MemConfig->PciData = 0xCFC;
+ MemConfig->CkeRankMapping = 0xAA;
+ //
+ // SA GV: 0 - Disabled, 1 - FixedLow, 2 - FixedHigh, 3 - Enabled
+ //
+ //
+ // Current Simics will fail in MRC training when SAGV enabled so need to by default disable SAGV.
+ //
+ MemConfig->SaGv = 3; // This only affects ULX/ULT and CPU steppings C0/J0 and above; otherwise SA GV is disabled.
+
+ MemConfig->Idd3n = 26;
+ MemConfig->Idd3p = 11;
+
+ MemConfig->RhPrevention = TRUE; // Row Hammer prevention.
+ MemConfig->RhSolution = HardwareRhp; // Type of solution to be used for RHP - 0/1 = HardwareRhp/Refresh2x
+ MemConfig->RhActProbability = OneIn2To11; // Activation probability for Hardware RHP
+
+ MemConfig->LpddrMemWriteLatencySet = 1; // Enable LPDDR3 WL Set B if supported by DRAM
+ MemConfig->EvLoaderDelay = 1;
+
+ MemConfig->DllBwEn1 = 1;
+ MemConfig->DllBwEn2 = 2;
+ MemConfig->DllBwEn3 = 2;
+
+ MemConfig->RetrainOnFastFail = 1; // Restart MRC in Cold mode if SW MemTest fails during Fast flow. 0 = Disabled, 1 = Enabled
+}
+
+
+static COMPONENT_BLOCK_ENTRY mSaIpBlocksPreMem[] = {
+ { &gSaMiscPeiPreMemConfigGuid, sizeof(SA_MISC_PEI_PREMEM_CONFIG), SA_MISC_PEI_PREMEM_CONFIG_REVISION, LoadSaMiscPeiPreMemDefault },
+ { &gMemoryConfigGuid, sizeof(MEMORY_CONFIGURATION), MEMORY_CONFIG_REVISION, LoadMemConfigDefault },
+ { &gMemoryConfigNoCrcGuid, sizeof(MEMORY_CONFIG_NO_CRC), MEMORY_CONFIG_REVISION, LoadMemConfigNoCrcDefault }
+};
+
+static COMPONENT_BLOCK_ENTRY mSaIpBlocks [] = {
+ {&gGraphicsPeiConfigGuid, sizeof (GRAPHICS_PEI_CONFIG), GRAPHICS_PEI_CONFIG_REVISION, LoadGraphichsPeiDefault},
+ {&gVtdConfigGuid, sizeof (VTD_CONFIG), VTD_CONFIG_REVISION, LoadVtdDefault}
+};
+
+/**
+ Get SA config block table total size.
+
+ @retval Size of SA config block table
+**/
+UINT16
+EFIAPI
+SaGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mSaIpBlocks[0], sizeof (mSaIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ Get SA config block table total size.
+
+ @retval Size of SA config block table
+**/
+UINT16
+EFIAPI
+SaGetConfigBlockTotalSizePreMem (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mSaIpBlocksPreMem[0], sizeof (mSaIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ SaAddConfigBlocksPreMem add all SA config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add SA config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SaAddConfigBlocksPreMem (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "SA AddConfigBlocks. TotalBlockCount = 0x%x\n", sizeof (mSaIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY)));
+ Status = AddComponentConfigBlocks (ConfigBlockTableAddress, &mSaIpBlocksPreMem[0], sizeof (mSaIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+ if (Status == EFI_SUCCESS) {
+ SaLoadSamplePolicyPreMem (ConfigBlockTableAddress);
+ }
+ return Status;
+}
+
+/**
+ SaAddConfigBlocks add all SA config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add SA config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+SaAddConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "SA AddConfigBlocks. TotalBlockCount = 0x%x\n", sizeof (mSaIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY)));
+
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mSaIpBlocks[0], sizeof (mSaIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.inf b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.inf
new file mode 100644
index 0000000000..0afd31b584
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLib.inf
@@ -0,0 +1,72 @@
+## @file
+# Component description file for the PeiSaPolicy library.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiSaPolicyLib
+FILE_GUID = d7022865-ef1b-449d-8c3f-ac36488c408b
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PeiSaPolicyLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+PeiServicesLib
+BaseMemoryLib
+MemoryAllocationLib
+ConfigBlockLib
+CpuMailboxLib
+SiConfigBlockLib
+RngLib
+SmbusLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdTsegSize
+gSiPkgTokenSpaceGuid.PcdMchBaseAddress
+gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress
+gSiPkgTokenSpaceGuid.PcdPeiMinMemorySize
+
+[Sources]
+PeiSaPolicyLib.c
+PeiSaPolicyLibrary.h
+MrcOemPlatform.c
+MrcOemPlatform.h
+SaPrintPolicy.c
+PeiSaPolicyLibSample.c
+
+[Sources.IA32]
+Ia32/MrcOemPlatform.asm | MSFT
+Ia32/MrcOemPlatform.S | GCC
+# Ia32/MrcOemPlatform.nasm | GCC # To support Nasm
+
+[Ppis]
+gSiPreMemPolicyPpiGuid ## CONSUMES
+gSiPolicyPpiGuid ## CONSUMES
+
+[Guids]
+gSaMiscPeiPreMemConfigGuid ## PRODUCES
+gMemoryConfigGuid ## PRODUCES
+gMemoryConfigNoCrcGuid ## PRODUCES
+gGraphicsPeiConfigGuid ## CONSUMES
+gVtdConfigGuid ## PRODUCES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibSample.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibSample.c
new file mode 100644
index 0000000000..a65349b29c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibSample.c
@@ -0,0 +1,281 @@
+/** @file
+ This file provides services for Sample PEI policy default initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <SaPolicyCommon.h>
+#include "PeiSaPolicyLibrary.h"
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/SmbusLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include "MrcOemPlatform.h"
+#include <Library/GpioLib.h>
+#include <GpioPinsSklH.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/RngLib.h>
+#include <Library/CpuMailboxLib.h>
+
+//
+// DQ byte mapping to CMD/CTL/CLK, from the CPU side - for SKL RVP, SKL SDS.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mDqByteMapSkl[2][6][2] = {
+ // Channel 0:
+ {
+ { 0x0F, 0xF0 }, // CLK0 goes to package 0 - Bytes[3:0], CLK1 goes to package 1 - Bytes[7:4]
+ { 0x00, 0xF0 }, // CmdN does not have CAA, CAB goes to Bytes[7:4]
+ { 0x0F, 0xF0 }, // CmdS CAA goes to Bytes[3:0], CmdS CAB goes to Byte[7:4]
+ { 0x0F, 0x00 }, // CKE CAA goes to Bytes[3:0], CKE does not have CAB
+ { 0xFF, 0x00 }, // CTL (CS) goes to all bytes
+ { 0xFF, 0x00 } // CA Vref is one for all bytes
+ },
+ // Channel 1:
+ {
+ { 0x33, 0xCC }, // CLK0 goes to package 0 - Bytes[3:0], CLK1 goes to package 1 - Bytes[7:4]
+ { 0x00, 0xCC }, // CmdN does not have CAA, CAB goes to Bytes[7:4]
+ { 0x33, 0xCC }, // CmdS CAA goes to Bytes[3:0], CmdS CAB goes to Byte[7:4]
+ { 0x33, 0x00 }, // CKE CAA goes to Bytes[3:0], CKE does not have CAB
+ { 0xFF, 0x00 }, // CTL (CS) goes to all bytes
+ { 0xFF, 0x00 } // CA Vref is one for all bytes
+ }
+};
+
+//
+// DQS byte swizzling between CPU and DRAM - for SKL RVP1, RVP3, RVP13
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mDqsMapCpu2DramSklRvp[2][8] = {
+ { 0, 1, 3, 2, 4, 5, 6, 7 }, // Channel 0
+ { 1, 0, 4, 5, 2, 3, 6, 7 } // Channel 1
+};
+
+//
+// Reference RCOMP resistors on motherboard - for SKL RVP1/RVP3
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 mRcompResistorSklRvp1[SA_MRC_MAX_RCOMP] = { 200, 81, 162 };
+//
+// RCOMP target values for RdOdt, WrDS, WrDSCmd, WrDSCtl, WrDSClk - for SKL RVP1/RVP3
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 mRcompTargetSklRvp1[SA_MRC_MAX_RCOMP_TARGETS] = { 100, 40, 40, 23, 40 };
+
+/**
+ Hynix H9CCNNN8JTMLAR-NTM_178b_DDP LPDDR3, 4Gb die (128Mx32), x32
+ or Elpida EDF8132A1MC-GD-F
+ or Samsung K4E8E304EB-EGCE
+ 1600, 12-15-15-34
+ 2 rank per channel, 2 SDRAMs per rank, 4x4Gb = 2GB total per channel
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSkylakeRvp3Spd[] = {
+ 0x24, ///< 0 Number of Serial PD Bytes Written / SPD Device Size
+ 0x20, ///< 1 SPD Revision
+ 0x0F, ///< 2 DRAM Device Type
+ 0x0E, ///< 3 Module Type
+ 0x14, ///< 4 SDRAM Density and Banks: 8 Banks, 4 Gb SDRAM density
+ 0x11, ///< 5 SDRAM Addressing: 14 Rows, 10 Columns
+ 0x95, ///< 6 SDRAM Package Type: DDP, 1 Channel per die, Signal Loading Matrix 1
+ 0x00, ///< 7 SDRAM Optional Features
+ 0x00, ///< 8 SDRAM Thermal and Refresh Options
+ 0x00, ///< 9 Other SDRAM Optional Features
+ 0x00, ///< 10 Reserved - must be coded as 0x00
+ 0x03, ///< 11 Module Nominal Voltage, VDD
+ 0x0B, ///< 12 Module Organization, SDRAM width: 32 bits, 2 Ranks
+ 0x23, ///< 13 Module Memory Bus Width: 2 channels, 64 bit channel bus width
+ 0x00, ///< 14 Module Thermal Sensor
+ 0x00, ///< 15 Extended Module Type
+ 0x00, ///< 16 Reserved - must be coded as 0x00
+ 0x00, ///< 17 Timebases
+ 0x0A, ///< 18 SDRAM Minimum Cycle Time (tCKmin)
+ 0xFF, ///< 19 SDRAM Minimum Cycle Time (tCKmax)
+ 0x54, ///< 20 CAS Latencies Supported, First Byte (tCk): 12 10 8
+ 0x00, ///< 21 CAS Latencies Supported, Second Byte
+ 0x00, ///< 22 CAS Latencies Supported, Third Byte
+ 0x00, ///< 23 CAS Latencies Supported, Fourth Byte
+ 0x78, ///< 24 Minimum CAS Latency Time (tAAmin)
+ 0x00, ///< 25 Read and Write Latency Set Options
+ 0x90, ///< 26 Minimum RAS# to CAS# Delay Time (tRCDmin)
+ 0xA8, ///< 27 Minimum Row Precharge Delay Time for all banks (tRPab)
+ 0x90, ///< 28 Minimum Row Precharge Delay Time per bank (tRPpb)
+ 0x10, ///< 29 Minimum Refresh Recovery Delay Time for all banks (tRFCab), Least Significant Byte
+ 0x04, ///< 30 Minimum Refresh Recovery Delay Time for all banks (tRFCab), Most Significant Byte
+ 0xE0, ///< 31 Minimum Refresh Recovery Delay Time for per bank (tRFCpb), Least Significant Byte
+ 0x01, ///< 32 Minimum Refresh Recovery Delay Time for per bank (tRFCpb), Most Significant Byte
+ 0, 0, 0, 0, 0, 0, 0, ///< 33 - 39
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 40 - 49
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 50 - 59
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 60 - 69 Connector to SDRAM Bit Mapping
+ 0, 0, 0, 0, 0, 0, 0, 0, ///< 70 - 77 Connector to SDRAM Bit Mapping
+ 0, 0, ///< 78 - 79
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 80 - 89
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 90 - 99
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 100 - 109
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 110 - 119
+ 0x00, ///< 120 Fine Offset for Minimum Row Precharge Delay Time per bank (tRPpb)
+ 0x00, ///< 121 Fine Offset for Minimum Row Precharge Delay Time for all banks (tRPab)
+ 0x00, ///< 122 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin)
+ 0x00, ///< 123 Fine Offset for Minimum CAS Latency Time (tAAmin)
+ 0x7F, ///< 124 Fine Offset for SDRAM Minimum Cycle Time (tCKmax)
+ 0x00, ///< 125 Fine Offset for SDRAM Minimum Cycle Time (tCKmin)
+ 0x00, ///< 126 CRC A
+ 0x00, ///< 127 CRC B
+ 0, 0, ///< 128 - 129
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 130 - 139
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 140 - 149
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 150 - 159
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 160 - 169
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 170 - 179
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 180 - 189
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 190 - 199
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 200 - 209
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 210 - 219
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 220 - 229
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 230 - 239
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 240 - 249
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 250 - 259
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 260 - 269
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 270 - 279
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 280 - 289
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 290 - 299
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 300 - 309
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 310 - 319
+ 0x00, ///< 320 Module Manufacturer ID Code, Least Significant Byte
+ 0x00, ///< 321 Module Manufacturer ID Code, Most Significant Byte
+ 0x00, ///< 322 Module Manufacturing Location
+ 0x00, ///< 323 Module Manufacturing Date Year
+ 0x00, ///< 324 Module Manufacturing Date Week
+ 0x55, ///< 325 Module Serial Number A
+ 0x00, ///< 326 Module Serial Number B
+ 0x00, ///< 327 Module Serial Number C
+ 0x00, ///< 328 Module Serial Number D
+ 0x20, 0x20, 0x20, 0x20, 0x20, ///< 329 - 333 Module Part Number: Unused bytes coded as ASCII Blanks (0x20)
+ 0x20, 0x20, 0x20, 0x20, 0x20, ///< 334 - 338 Module Part Number
+ 0x20, 0x20, 0x20, 0x20, 0x20, ///< 339 - 343 Module Part Number
+ 0x20, 0x20, 0x20, 0x20, 0x20, ///< 344 - 348 Module Part Number
+ 0x00, ///< 349 Module Revision Code
+ 0x00, ///< 350 DRAM Manufacturer ID Code, Least Significant Byte
+ 0x00, ///< 351 DRAM Manufacturer ID Code, Most Significant Byte
+ 0x00, ///< 352 DRAM Stepping
+ 0, 0, 0, 0, 0, 0, 0, ///< 353 - 359
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 360 - 369
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 370 - 379
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 380 - 389
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 390 - 399
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 400 - 409
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 410 - 419
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 420 - 429
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 430 - 439
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 440 - 449
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 450 - 459
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 460 - 469
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 470 - 479
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 480 - 489
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 490 - 499
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ///< 500 - 509
+ 0, 0 ///< 510 - 511
+};
+
+#define SaIoRead8 IoRead8
+#define SaIoRead16 IoRead16
+#define SaIoRead32 IoRead32
+#define SaIoWrite8 IoWrite8
+#define SaIoWrite16 IoWrite16
+#define SaIoWrite32 IoWrite32
+#define SaCopyMem CopyMem
+#define SaSetMem SetMem
+#define SaLShiftU64 LShiftU64
+#define SaRShiftU64 RShiftU64
+#define SaMultU64x32 MultU64x32
+
+/**
+ SaLoadSamplePolicyPreMem - Load some policy default for reference board.
+
+ @param[in] ConfigBlockTableAddress The pointer for SA config blocks
+
+**/
+VOID
+SaLoadSamplePolicyPreMem (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ SA_FUNCTION_CALLS *MemCall;
+ EFI_STATUS Status;
+ MEMORY_CONFIG_NO_CRC *MemConfigNoCrc;
+
+ MemConfigNoCrc = NULL;
+ Status = GetConfigBlock (ConfigBlockTableAddress, &gMemoryConfigNoCrcGuid, (VOID *) &MemConfigNoCrc);
+ ASSERT_EFI_ERROR (Status);
+
+ if (MemConfigNoCrc == NULL) {
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO, "Applying Sample policy defaults for RVP3\n"));
+ MemCall = &MemConfigNoCrc->SaCall;
+ MemCall->IoRead8 = &SaIoRead8;
+ MemCall->IoRead16 = &SaIoRead16;
+ MemCall->IoRead32 = &SaIoRead32;
+ MemCall->IoWrite8 = &SaIoWrite8;
+ MemCall->IoWrite16 = &SaIoWrite16;
+ MemCall->IoWrite32 = &SaIoWrite32;
+ MemCall->MmioRead8 = &MmioRead8;
+ MemCall->MmioRead16 = &MmioRead16;
+ MemCall->MmioRead32 = &MmioRead32;
+ MemCall->MmioRead64 = &SaMmioRead64;
+ MemCall->MmioWrite8 = &MmioWrite8;
+ MemCall->MmioWrite16 = &MmioWrite16;
+ MemCall->MmioWrite32 = &MmioWrite32;
+ MemCall->MmioWrite64 = &SaMmioWrite64;
+ MemCall->SmbusRead8 = &SmBusReadDataByte;
+ MemCall->SmbusRead16 = &SmBusReadDataWord;
+ MemCall->SmbusWrite8 = &SmBusWriteDataByte;
+ MemCall->SmbusWrite16 = &SmBusWriteDataWord;
+ MemCall->GetPciDeviceAddress = &GetPciDeviceAddress;
+ MemCall->GetPcieDeviceAddress = &GetPcieDeviceAddress;
+ MemCall->GetRtcTime = &GetRtcTime;
+ MemCall->GetCpuTime = &GetCpuTime;
+ MemCall->CopyMem = &SaCopyMem;
+ MemCall->SetMem = &SaSetMem;
+ MemCall->SetMemWord = &SetMemWord;
+ MemCall->SetMemDword = &SetMemDword;
+ MemCall->LeftShift64 = &SaLShiftU64;
+ MemCall->RightShift64 = &SaRShiftU64;
+ MemCall->MultU64x32 = &SaMultU64x32;
+ MemCall->DivU64x64 = &DivU64x64Remainder;
+ MemCall->GetSpdData = &GetSpdData;
+ MemCall->GetRandomNumber = &GetRandomNumber32;
+ MemCall->CpuMailboxRead = &MailboxRead;
+ MemCall->CpuMailboxWrite = &MailboxWrite;
+ MemCall->GetMemoryVdd = &GetMemoryVdd;
+ MemCall->SetMemoryVdd = &SetMemoryVdd;
+ MemCall->CheckPoint = &CheckPoint;
+ MemCall->DebugHook = &DebugHook;
+ MemCall->DebugPrint = &SaDebugPrint;
+ MemCall->GetRtcCmos = &PeiRtcRead;
+ MemCall->ReadMsr64 = &AsmReadMsr64;
+ MemCall->WriteMsr64 = &AsmWriteMsr64;
+ MemCall->MrcReturnFromSmc = &ReturnFromSmc;
+ MemCall->MrcDramReset = &SaDramReset;
+
+ //
+ // RCOMP resistors and target values: board-dependent
+ //
+ CopyMem ((VOID *) MemConfigNoCrc->RcompData->RcompResistor, mRcompResistorSklRvp1, sizeof (mRcompResistorSklRvp1));
+ CopyMem ((VOID *) MemConfigNoCrc->RcompData->RcompTarget, mRcompTargetSklRvp1, sizeof (mRcompTargetSklRvp1));
+
+ CopyMem ((VOID *) MemConfigNoCrc->SpdData->SpdData[0][0], mSkylakeRvp3Spd, sizeof (mSkylakeRvp3Spd));
+ CopyMem ((VOID *) MemConfigNoCrc->SpdData->SpdData[1][0], mSkylakeRvp3Spd, sizeof (mSkylakeRvp3Spd));
+ CopyMem ((VOID *) MemConfigNoCrc->DqByteMap, mDqByteMapSkl, sizeof (UINT8) * SA_MC_MAX_CHANNELS * SA_MRC_ITERATION_MAX *2);
+ CopyMem ((VOID *) MemConfigNoCrc->DqsMap, mDqsMapCpu2DramSklRvp, sizeof (UINT8) * SA_MC_MAX_CHANNELS * SA_MC_MAX_BYTES_NO_ECC);
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibrary.h
new file mode 100644
index 0000000000..e7fe3d2fcf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/PeiSaPolicyLibrary.h
@@ -0,0 +1,44 @@
+/** @file
+ Header file for the PeiSaPolicy library.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _PEI_SA_POLICY_LIBRARY_H_
+#define _PEI_SA_POLICY_LIBRARY_H_
+
+#include <CpuRegs.h>
+#include <SaPolicyCommon.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/SmbusLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/PeiSaPolicyLib.h>
+#include <Library/SiConfigBlockLib.h>
+
+/**
+ SaLoadSamplePolicyPreMem - Load some policy default for reference board.
+
+ @param[in] ConfigBlockTableAddress The pointer for SA config blocks
+
+**/
+VOID
+SaLoadSamplePolicyPreMem (
+ IN VOID *ConfigBlockTableAddress
+ );
+#endif // _PEI_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/SaPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/SaPrintPolicy.c
new file mode 100644
index 0000000000..0a6ddb8a8f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/Library/PeiSaPolicyLib/SaPrintPolicy.c
@@ -0,0 +1,326 @@
+/** @file
+ This file provides service for PEI phase policy printing
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "PeiSaPolicyLibrary.h"
+#include <Library/GpioNativeLib.h>
+
+/**
+ This function prints the PEI phase PreMem policy.
+
+ @param[in] SiPolicyPreMemPpi - Instance of SI_PREMEM_POLICY_PPI
+**/
+VOID
+EFIAPI
+SaPrintPolicyPpiPreMem (
+ IN SI_PREMEM_POLICY_PPI *SiPolicyPreMemPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ INTN Index;
+ INTN Index2;
+ EFI_STATUS Status;
+ SA_MISC_PEI_PREMEM_CONFIG *MiscPeiPreMemConfig;
+ MEMORY_CONFIGURATION *MemConfig;
+ MEMORY_CONFIG_NO_CRC *MemConfigNoCrc;
+
+ //
+ // Get requisite IP Config Blocks which needs to be used here
+ //
+ Status = GetConfigBlock ((VOID *)SiPolicyPreMemPpi, &gSaMiscPeiPreMemConfigGuid, (VOID *) &MiscPeiPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *)SiPolicyPreMemPpi, &gMemoryConfigGuid, (VOID *) &MemConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *)SiPolicyPreMemPpi, &gMemoryConfigNoCrcGuid, (VOID *) &MemConfigNoCrc);
+ ASSERT_EFI_ERROR (Status);
+
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (PEI PreMem) Print BEGIN -----------------\n"));
+ DEBUG ((DEBUG_INFO, "Revision : 0x%x\n", SiPolicyPreMemPpi->TableHeader.Header.Revision));
+ ASSERT (SiPolicyPreMemPpi->TableHeader.Header.Revision == SI_PREMEM_POLICY_REVISION);
+
+ DEBUG ((DEBUG_INFO, "------------------------ SA_MISC_PEI_PREMEM_CONFIG -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : %d\n", MiscPeiPreMemConfig->Header.Revision));
+ ASSERT (MiscPeiPreMemConfig->Header.Revision == SA_MISC_PEI_PREMEM_CONFIG_REVISION);
+ DEBUG ((DEBUG_INFO, " SpdAddressTable[%d] :", SA_MC_MAX_SOCKETS));
+ for (Index = 0; Index < SA_MC_MAX_SOCKETS; Index++) {
+ DEBUG ((DEBUG_INFO, " 0x%x", MiscPeiPreMemConfig->SpdAddressTable[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, " MchBar : 0x%x\n", MiscPeiPreMemConfig->MchBar));
+ DEBUG ((DEBUG_INFO, "------------------------ MEMORY_CONFIG ------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Guid : %g\n", &MemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, " Revision : %d\n", MemConfig->Header.Revision));
+ ASSERT (MemConfig->Header.Revision == MEMORY_CONFIG_REVISION);
+ DEBUG ((DEBUG_INFO, " Size : 0x%x\n", MemConfig->Header.GuidHob.Header.HobLength));
+ DEBUG ((DEBUG_INFO, " HobBufferSize : 0x%x\n", MemConfig->HobBufferSize));
+ DEBUG ((DEBUG_INFO, " EccSupport : 0x%x\n", MemConfig->EccSupport));
+ DEBUG ((DEBUG_INFO, " DdrFreqLimit: %d\n", MemConfig->DdrFreqLimit));
+ DEBUG ((DEBUG_INFO, " SpdProfileSelected : 0x%x\n", MemConfig->SpdProfileSelected));
+ DEBUG ((DEBUG_INFO, " tCL : 0x%x\n", MemConfig->tCL));
+ DEBUG ((DEBUG_INFO, " tRCDtRP : 0x%x\n", MemConfig->tRCDtRP));
+ DEBUG ((DEBUG_INFO, " tRAS : 0x%x\n", MemConfig->tRAS));
+ DEBUG ((DEBUG_INFO, " tWR : 0x%x\n", MemConfig->tWR));
+ DEBUG ((DEBUG_INFO, " tRFC : 0x%x\n", MemConfig->tRFC));
+ DEBUG ((DEBUG_INFO, " tRRD : 0x%x\n", MemConfig->tRRD));
+ DEBUG ((DEBUG_INFO, " tWTR : 0x%x\n", MemConfig->tWTR));
+ DEBUG ((DEBUG_INFO, " tRTP : 0x%x\n", MemConfig->tRTP));
+ DEBUG ((DEBUG_INFO, " tFAW : 0x%x\n", MemConfig->tFAW));
+ DEBUG ((DEBUG_INFO, " tCWL : 0x%x\n", MemConfig->tCWL));
+ DEBUG ((DEBUG_INFO, " tREFI : 0x%x\n", MemConfig->tREFI));
+ DEBUG ((DEBUG_INFO, " NModeSupport : 0x%x\n", MemConfig->NModeSupport));
+ DEBUG ((DEBUG_INFO, " VddVoltage : %d\n", MemConfig->VddVoltage));
+ DEBUG ((DEBUG_INFO, " ThermalManagement : 0x%x\n", MemConfig->ThermalManagement));
+ DEBUG ((DEBUG_INFO, " PeciInjectedTemp : 0x%x\n", MemConfig->PeciInjectedTemp));
+ DEBUG ((DEBUG_INFO, " ExttsViaTsOnBoard : 0x%x\n", MemConfig->ExttsViaTsOnBoard));
+ DEBUG ((DEBUG_INFO, " ExttsViaTsOnDimm : 0x%x\n", MemConfig->ExttsViaTsOnDimm));
+ DEBUG ((DEBUG_INFO, " VirtualTempSensor : 0x%x\n", MemConfig->VirtualTempSensor));
+
+ DEBUG ((DEBUG_INFO, " DisableDimmChannel[%d] :", SA_MC_MAX_CHANNELS));
+ for (Index = 0; Index < SA_MC_MAX_CHANNELS; Index++) {
+ DEBUG ((DEBUG_INFO, " 0x%x", MemConfig->DisableDimmChannel[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, " RemapEnable : 0x%x\n", MemConfig->RemapEnable));
+ DEBUG ((DEBUG_INFO, " ScramblerSupport : 0x%x\n", MemConfig->ScramblerSupport));
+ DEBUG ((DEBUG_INFO, " SerialDebug : 0x%x\n", MemConfigNoCrc->SerialDebugLevel));
+ DEBUG ((DEBUG_INFO, " McLock : 0x%x\n", MemConfig->McLock));
+ DEBUG ((DEBUG_INFO, " ProbelessTrace : 0x%x\n", MemConfig->ProbelessTrace));
+ DEBUG ((DEBUG_INFO, " GdxcIotSize : 0x%x\n", MemConfig->GdxcIotSize));
+ DEBUG ((DEBUG_INFO, " GdxcMotSize : 0x%x\n", MemConfig->GdxcMotSize));
+
+ DEBUG ((DEBUG_INFO, " ECT : 0x%x\n", MemConfig->ECT));
+ DEBUG ((DEBUG_INFO, " SOT : 0x%x\n", MemConfig->SOT));
+ DEBUG ((DEBUG_INFO, " ERDMPRTC2D : 0x%x\n", MemConfig->ERDMPRTC2D));
+ DEBUG ((DEBUG_INFO, " RDMPRT : 0x%x\n", MemConfig->RDMPRT));
+ DEBUG ((DEBUG_INFO, " RCVET : 0x%x\n", MemConfig->RCVET));
+ DEBUG ((DEBUG_INFO, " JWRL : 0x%x\n", MemConfig->JWRL));
+ DEBUG ((DEBUG_INFO, " EWRDSEQ : 0x%x\n", MemConfig->EWRDSEQ));
+ DEBUG ((DEBUG_INFO, " EWRTC2D : 0x%x\n", MemConfig->EWRTC2D));
+ DEBUG ((DEBUG_INFO, " ERDTC2D : 0x%x\n", MemConfig->ERDTC2D));
+ DEBUG ((DEBUG_INFO, " WRTC1D : 0x%x\n", MemConfig->WRTC1D));
+ DEBUG ((DEBUG_INFO, " WRVC1D : 0x%x\n", MemConfig->WRVC1D));
+ DEBUG ((DEBUG_INFO, " RDTC1D : 0x%x\n", MemConfig->RDTC1D));
+ DEBUG ((DEBUG_INFO, " DIMMODTT : 0x%x\n", MemConfig->DIMMODTT));
+ DEBUG ((DEBUG_INFO, " DIMMRONT : 0x%x\n", MemConfig->DIMMRONT));
+ DEBUG ((DEBUG_INFO, " WRDSEQT : 0x%x\n", MemConfig->WRDSEQT));
+ DEBUG ((DEBUG_INFO, " WRSRT : 0x%x\n", MemConfig->WRSRT));
+ DEBUG ((DEBUG_INFO, " RDODTT : 0x%x\n", MemConfig->RDODTT));
+ DEBUG ((DEBUG_INFO, " RDEQT : 0x%x\n", MemConfig->RDEQT));
+ DEBUG ((DEBUG_INFO, " RDAPT : 0x%x\n", MemConfig->RDAPT));
+ DEBUG ((DEBUG_INFO, " WRTC2D : 0x%x\n", MemConfig->WRTC2D));
+ DEBUG ((DEBUG_INFO, " RDTC2D : 0x%x\n", MemConfig->RDTC2D));
+ DEBUG ((DEBUG_INFO, " WRVC2D : 0x%x\n", MemConfig->WRVC2D));
+ DEBUG ((DEBUG_INFO, " RDVC2D : 0x%x\n", MemConfig->RDVC2D));
+ DEBUG ((DEBUG_INFO, " CMDVC : 0x%x\n", MemConfig->CMDVC));
+ DEBUG ((DEBUG_INFO, " LCT : 0x%x\n", MemConfig->LCT));
+ DEBUG ((DEBUG_INFO, " RTL : 0x%x\n", MemConfig->RTL));
+ DEBUG ((DEBUG_INFO, " TAT : 0x%x\n", MemConfig->TAT));
+ DEBUG ((DEBUG_INFO, " RMT : 0x%x\n", MemConfig->RMT));
+ DEBUG ((DEBUG_INFO, " MEMTST : 0x%x\n", MemConfig->MEMTST));
+ DEBUG ((DEBUG_INFO, " ALIASCHK : 0x%x\n", MemConfig->ALIASCHK));
+ DEBUG ((DEBUG_INFO, " RCVENC1D : 0x%x\n", MemConfig->RCVENC1D));
+ DEBUG ((DEBUG_INFO, " RMC : 0x%x\n", MemConfig->RMC));
+ DEBUG ((DEBUG_INFO, " WRDSUDT : 0x%x\n", MemConfig->WRDSUDT));
+ DEBUG ((DEBUG_INFO, " CMDSR: %d\n CMDDSEQ: %d\n CMDNORM: %d\n",
+ MemConfig->CMDSR, MemConfig->CMDDSEQ, MemConfig->CMDNORM));
+
+ DEBUG ((DEBUG_INFO, " VddSettleWaitTime : 0x%x\n", MemConfig->VddSettleWaitTime));
+ DEBUG ((DEBUG_INFO, " RefClk : 0x%x\n", MemConfig->RefClk));
+ DEBUG ((DEBUG_INFO, " Ratio : 0x%x\n", MemConfig->Ratio));
+ DEBUG ((DEBUG_INFO, " OddRatioMode : 0x%x\n", MemConfig->OddRatioMode));
+ DEBUG ((DEBUG_INFO, " MrcTimeMeasure : 0x%x\n", MemConfig->MrcTimeMeasure));
+ DEBUG ((DEBUG_INFO, " MrcFastBoot : 0x%x\n", MemConfig->MrcFastBoot));
+ DEBUG ((DEBUG_INFO, " DqPinsInterleaved : 0x%x\n", MemConfig->DqPinsInterleaved));
+ DEBUG ((DEBUG_INFO, " MrcSafeConfig : 0x%x\n", MemConfig->MrcSafeConfig));
+
+ DEBUG ((DEBUG_INFO, " PowerDownMode : 0x%x\n", MemConfig->PowerDownMode));
+ DEBUG ((DEBUG_INFO, " PwdwnIdleCounter : 0x%x\n", MemConfig->PwdwnIdleCounter));
+ DEBUG ((DEBUG_INFO, " RankInterleave : 0x%x\n", MemConfig->RankInterleave));
+ DEBUG ((DEBUG_INFO, " EnhancedInterleave : 0x%x\n", MemConfig->EnhancedInterleave));
+ DEBUG ((DEBUG_INFO, " WeaklockEn : 0x%x\n", MemConfig->WeaklockEn));
+ DEBUG ((DEBUG_INFO, " EnCmdRate : 0x%x\n", MemConfig->EnCmdRate));
+ DEBUG ((DEBUG_INFO, " CmdTriStateDis : 0x%x\n", MemConfig->CmdTriStateDis));
+ DEBUG ((DEBUG_INFO, " BClkFrequency: %d Hz\n", MemConfig->BClkFrequency));
+ DEBUG ((DEBUG_INFO, " MemoryTrace : 0x%x\n", MemConfig->MemoryTrace));
+ DEBUG ((DEBUG_INFO, " ChHashEnable : 0x%x\n", MemConfig->ChHashEnable));
+ DEBUG ((DEBUG_INFO, " ChHashMask : 0x%x\n", MemConfig->ChHashMask));
+ DEBUG ((DEBUG_INFO, " ChHashInterleaveBit : 0x%x\n", MemConfig->ChHashInterleaveBit));
+ DEBUG ((DEBUG_INFO, " EnableExtts : 0x%x\n", MemConfig->EnableExtts));
+ DEBUG ((DEBUG_INFO, " EnableCltm : 0x%x\n", MemConfig->EnableCltm));
+ DEBUG ((DEBUG_INFO, " EnableOltm : 0x%x\n", MemConfig->EnableOltm));
+ DEBUG ((DEBUG_INFO, " EnablePwrDn : 0x%x\n", MemConfig->EnablePwrDn));
+ DEBUG ((DEBUG_INFO, " EnablePwrDnLpddr : 0x%x\n", MemConfig->EnablePwrDnLpddr));
+ DEBUG ((DEBUG_INFO, " Refresh2X : 0x%x\n", MemConfig->Refresh2X));
+ DEBUG ((DEBUG_INFO, " DdrThermalSensor : 0x%x\n", MemConfig->DdrThermalSensor));
+ DEBUG ((DEBUG_INFO, " LockPTMregs : 0x%x\n", MemConfig->LockPTMregs));
+ DEBUG ((DEBUG_INFO, " UserPowerWeightsEn : 0x%x\n", MemConfig->UserPowerWeightsEn));
+ DEBUG ((DEBUG_INFO, " EnergyScaleFact : 0x%x\n", MemConfig->EnergyScaleFact));
+ DEBUG ((DEBUG_INFO, " RaplPwrFlCh1 : 0x%x\n", MemConfig->RaplPwrFlCh1));
+ DEBUG ((DEBUG_INFO, " RaplPwrFlCh0 : 0x%x\n", MemConfig->RaplPwrFlCh0));
+ DEBUG ((DEBUG_INFO, " RaplLim2Lock : 0x%x\n", MemConfig->RaplLim2Lock));
+ DEBUG ((DEBUG_INFO, " RaplLim2WindX : 0x%x\n", MemConfig->RaplLim2WindX));
+ DEBUG ((DEBUG_INFO, " RaplLim2WindY : 0x%x\n", MemConfig->RaplLim2WindY));
+ DEBUG ((DEBUG_INFO, " RaplLim2Ena : 0x%x\n", MemConfig->RaplLim2Ena));
+ DEBUG ((DEBUG_INFO, " RaplLim2Pwr : 0x%x\n", MemConfig->RaplLim2Pwr));
+ DEBUG ((DEBUG_INFO, " RaplLim1WindX : 0x%x\n", MemConfig->RaplLim1WindX));
+ DEBUG ((DEBUG_INFO, " RaplLim1WindY : 0x%x\n", MemConfig->RaplLim1WindY));
+ DEBUG ((DEBUG_INFO, " RaplLim1Ena : 0x%x\n", MemConfig->RaplLim1Ena));
+ DEBUG ((DEBUG_INFO, " RaplLim1Pwr : 0x%x\n", MemConfig->RaplLim1Pwr));
+ DEBUG ((DEBUG_INFO, " WarmThresholdCh0Dimm0 : 0x%x\n", MemConfig->WarmThresholdCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " WarmThresholdCh0Dimm1 : 0x%x\n", MemConfig->WarmThresholdCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " WarmThresholdCh1Dimm0 : 0x%x\n", MemConfig->WarmThresholdCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " WarmThresholdCh1Dimm1 : 0x%x\n", MemConfig->WarmThresholdCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " HotThresholdCh0Dimm0 : 0x%x\n", MemConfig->HotThresholdCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " HotThresholdCh0Dimm1 : 0x%x\n", MemConfig->HotThresholdCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " HotThresholdCh1Dimm0 : 0x%x\n", MemConfig->HotThresholdCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " HotThresholdCh1Dimm1 : 0x%x\n", MemConfig->HotThresholdCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " WarmBudgetCh0Dimm0 : 0x%x\n", MemConfig->WarmBudgetCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " WarmBudgetCh0Dimm1 : 0x%x\n", MemConfig->WarmBudgetCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " WarmBudgetCh1Dimm0 : 0x%x\n", MemConfig->WarmBudgetCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " WarmBudgetCh1Dimm1 : 0x%x\n", MemConfig->WarmBudgetCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " HotBudgetCh0Dimm0 : 0x%x\n", MemConfig->HotBudgetCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " HotBudgetCh0Dimm1 : 0x%x\n", MemConfig->HotBudgetCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " HotBudgetCh1Dimm0 : 0x%x\n", MemConfig->HotBudgetCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " HotBudgetCh1Dimm1 : 0x%x\n", MemConfig->HotBudgetCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " IdleEnergyCh0Dimm0 : 0x%x\n", MemConfig->IdleEnergyCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " IdleEnergyCh0Dimm1 : 0x%x\n", MemConfig->IdleEnergyCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " IdleEnergyCh1Dimm0 : 0x%x\n", MemConfig->IdleEnergyCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " IdleEnergyCh1Dimm1 : 0x%x\n", MemConfig->IdleEnergyCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " PdEnergyCh0Dimm0 : 0x%x\n", MemConfig->PdEnergyCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " PdEnergyCh0Dimm1 : 0x%x\n", MemConfig->PdEnergyCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " PdEnergyCh1Dimm0 : 0x%x\n", MemConfig->PdEnergyCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " PdEnergyCh1Dimm1 : 0x%x\n", MemConfig->PdEnergyCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " ActEnergyCh0Dimm0 : 0x%x\n", MemConfig->ActEnergyCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " ActEnergyCh0Dimm1 : 0x%x\n", MemConfig->ActEnergyCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " ActEnergyCh1Dimm0 : 0x%x\n", MemConfig->ActEnergyCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " ActEnergyCh1Dimm1 : 0x%x\n", MemConfig->ActEnergyCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " RdEnergyCh0Dimm0 : 0x%x\n", MemConfig->RdEnergyCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " RdEnergyCh0Dimm1 : 0x%x\n", MemConfig->RdEnergyCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " RdEnergyCh1Dimm0 : 0x%x\n", MemConfig->RdEnergyCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " RdEnergyCh1Dimm1 : 0x%x\n", MemConfig->RdEnergyCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " WrEnergyCh0Dimm0 : 0x%x\n", MemConfig->WrEnergyCh0Dimm0));
+ DEBUG ((DEBUG_INFO, " WrEnergyCh0Dimm1 : 0x%x\n", MemConfig->WrEnergyCh0Dimm1));
+ DEBUG ((DEBUG_INFO, " WrEnergyCh1Dimm0 : 0x%x\n", MemConfig->WrEnergyCh1Dimm0));
+ DEBUG ((DEBUG_INFO, " WrEnergyCh1Dimm1 : 0x%x\n", MemConfig->WrEnergyCh1Dimm1));
+ DEBUG ((DEBUG_INFO, " SrefCfgEna : 0x%x\n", MemConfig->SrefCfgEna));
+ DEBUG ((DEBUG_INFO, " SrefCfgIdleTmr : 0x%x\n", MemConfig->SrefCfgIdleTmr));
+ DEBUG ((DEBUG_INFO, " ThrtCkeMinDefeat : 0x%x\n", MemConfig->ThrtCkeMinDefeat));
+ DEBUG ((DEBUG_INFO, " ThrtCkeMinTmr : 0x%x\n", MemConfig->ThrtCkeMinTmr));
+ DEBUG ((DEBUG_INFO, " ThrtCkeMinDefeatLpddr : 0x%x\n", MemConfig->ThrtCkeMinDefeatLpddr));
+ DEBUG ((DEBUG_INFO, " ThrtCkeMinTmrLpddr : 0x%x\n", MemConfig->ThrtCkeMinTmrLpddr));
+ DEBUG ((DEBUG_INFO, " AutoSelfRefreshSupport : 0x%x\n", MemConfig->AutoSelfRefreshSupport));
+ DEBUG ((DEBUG_INFO, " ExtTemperatureSupport : 0x%x\n", MemConfig->ExtTemperatureSupport));
+ DEBUG ((DEBUG_INFO, " MaxRttWr : 0x%x\n", MemConfig->MaxRttWr));
+ DEBUG ((DEBUG_INFO, " MobilePlatform : 0x%x\n", MemConfig->MobilePlatform));
+ DEBUG ((DEBUG_INFO, " Force1Dpc : 0x%x\n", MemConfig->Force1Dpc));
+
+
+ DEBUG ((DEBUG_INFO, " ForceSingleRank : 0x%x\n", MemConfig->ForceSingleRank));
+ DEBUG ((DEBUG_INFO, " PciIndex : 0x%x\n", MemConfig->PciIndex));
+ DEBUG ((DEBUG_INFO, " PciData : 0x%x\n", MemConfig->PciData));
+ DEBUG ((DEBUG_INFO, " CkeRankMapping : 0x%x\n", MemConfig->CkeRankMapping));
+ DEBUG ((DEBUG_INFO, " RhPrevention : 0x%x\n", MemConfig->RhPrevention));
+ DEBUG ((DEBUG_INFO, " RhSolution : 0x%x\n", MemConfig->RhSolution));
+ DEBUG ((DEBUG_INFO, " RhActProbability : 0x%x\n", MemConfig->RhActProbability));
+ DEBUG ((DEBUG_INFO, " VttTermination : 0x%x\n", MemConfig->VttTermination));
+ DEBUG ((DEBUG_INFO, " VttCompForVsshi : 0x%x\n", MemConfig->VttCompForVsshi));
+ DEBUG ((DEBUG_INFO, " BerEnable : 0x%x\n", MemConfig->BerEnable));
+ for (Index = 0; Index < 4; Index++) {
+ DEBUG ((DEBUG_INFO, " BerAddress[%d] : 0x%x\n",Index , MemConfig->BerAddress[Index]));
+ }
+ DEBUG ((DEBUG_INFO, " CleanMemory : 0x%x\n", MemConfigNoCrc->CleanMemory));
+ DEBUG ((DEBUG_INFO, " ExitOnFailure : 0x%x\n", MemConfig->ExitOnFailure));
+ DEBUG ((DEBUG_INFO, " Vc1ReadMeter : 0x%x\n", MemConfig->Vc1ReadMeter));
+ DEBUG ((DEBUG_INFO, " Vc1ReadMeterTimeWindow : 0x%x\n", MemConfig->Vc1ReadMeterTimeWindow));
+ DEBUG ((DEBUG_INFO, " Vc1ReadMeterThreshold : 0x%x\n", MemConfig->Vc1ReadMeterThreshold));
+ DEBUG ((DEBUG_INFO, " SaGv : 0x%x\n", MemConfig->SaGv));
+ DEBUG ((DEBUG_INFO, " FreqSaGvLow : 0x%x\n", MemConfig->FreqSaGvLow));
+ DEBUG ((DEBUG_INFO, " StrongWkLeaker : 0x%x\n", MemConfig->StrongWkLeaker));
+ DEBUG ((DEBUG_INFO, " CaVrefConfig : 0x%x\n", MemConfig->CaVrefConfig));
+ DEBUG ((DEBUG_INFO, " EvLoader : 0x%x\n", MemConfig->EvLoader));
+ DEBUG ((DEBUG_INFO, " EvLoaderDelay : 0x%x\n", MemConfig->EvLoaderDelay));
+ DEBUG ((DEBUG_INFO, " PlatformMemorySize : 0x%x\n", MemConfigNoCrc->PlatformMemorySize));
+ DEBUG ((DEBUG_INFO, " SmramMask : 0x%x\n", MemConfig->SmramMask));
+ DEBUG ((DEBUG_INFO, " DllBwEn0: %d\n DllBwEn1: %d\n DllBwEn2: %d\n DllBwEn3: %d\n",
+ MemConfig->DllBwEn0, MemConfig->DllBwEn1, MemConfig->DllBwEn2, MemConfig->DllBwEn3));
+ DEBUG ((DEBUG_INFO, " RetrainOnFastFail: %d\n ForceOltmOrRefresh2x: %d\n",
+ MemConfig->RetrainOnFastFail, MemConfig->ForceOltmOrRefresh2x));
+ for (Index = 0; Index < SA_MC_MAX_CHANNELS; Index++) {
+ DEBUG ((DEBUG_INFO, " DqByteMapCh%d : ", Index));
+ for (Index2 = 0; Index2 < SA_MRC_ITERATION_MAX; Index2++) {
+ DEBUG ((DEBUG_INFO, "0x%02x ", MemConfigNoCrc->DqByteMap->DqByteMap[Index][Index2][0]));
+ DEBUG ((DEBUG_INFO, "0x%02x ", MemConfigNoCrc->DqByteMap->DqByteMap[Index][Index2][1]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+ for (Index = 0; Index < SA_MC_MAX_CHANNELS; Index++) {
+ DEBUG ((DEBUG_INFO, " DqsMapCpu2DramCh%d : ", Index));
+ for (Index2 = 0; Index2 < SA_MC_MAX_BYTES_NO_ECC; Index2++) {
+ DEBUG ((DEBUG_INFO, "%d ", MemConfigNoCrc->DqsMap->DqsMapCpu2Dram[Index][Index2]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (PEI PreMem) Print END -----------------\n"));
+ DEBUG_CODE_END ();
+ return;
+}
+
+/**
+ This function prints the PEI phase policy.
+
+ @param[in] SiPolicyPpi - Instance of SI_POLICY_PPI
+**/
+VOID
+EFIAPI
+SaPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ GRAPHICS_PEI_CONFIG *GtConfig;
+ INTN Index;
+ VTD_CONFIG *Vtd;
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gVtdConfigGuid, (VOID *) &Vtd);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gGraphicsPeiConfigGuid, (VOID *) &GtConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (PEI) Print BEGIN -----------------\n"));
+ DEBUG ((DEBUG_INFO, "Revision : 0x%x\n", SiPolicyPpi->TableHeader.Header.Revision));
+ ASSERT (SiPolicyPpi->TableHeader.Header.Revision == SI_POLICY_REVISION);
+ DEBUG ((DEBUG_INFO, "------------------------ GRAPHICS_PEI_CONFIG -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : %d\n", GtConfig->Header.Revision));
+ ASSERT (GtConfig->Header.Revision == GRAPHICS_PEI_CONFIG_REVISION);
+ DEBUG ((DEBUG_INFO, " PeiGraphicsPeimInit : 0x%x\n", GtConfig->PeiGraphicsPeimInit));
+ DEBUG ((DEBUG_INFO, " LogoPtr : 0x%x\n", GtConfig->LogoPtr));
+ DEBUG ((DEBUG_INFO, " LogoSize : 0x%x\n", GtConfig->LogoSize));
+ DEBUG ((DEBUG_INFO, " GraphicsConfigPtr : 0x%x\n", GtConfig->GraphicsConfigPtr));
+ DEBUG ((DEBUG_INFO, "------------------------ VTD_CONFIG -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : %d\n", Vtd->Header.Revision));
+ ASSERT (Vtd->Header.Revision == VTD_CONFIG_REVISION);
+ DEBUG ((DEBUG_INFO, " VtdDisable : 0x%x\n", Vtd->VtdDisable));
+ DEBUG ((DEBUG_INFO, " X2ApicOptOut : 0x%x\n", Vtd->X2ApicOptOut));
+ DEBUG ((DEBUG_INFO, " VtdBaseAddress[%d] :", SA_VTD_ENGINE_NUMBER));
+ for (Index = 0; Index < SA_VTD_ENGINE_NUMBER; Index++) {
+ DEBUG ((DEBUG_INFO, " 0x%x", Vtd->BaseAddress[Index]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (PEI) Print END -----------------\n"));
+ DEBUG_CODE_END ();
+ return;
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcCommonTypes.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcCommonTypes.h
new file mode 100644
index 0000000000..792b2ca58d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcCommonTypes.h
@@ -0,0 +1,235 @@
+/** @file
+ This file contains the definitions common to the MRC API and other APIs.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MrcCommonTypes_h_
+#define _MrcCommonTypes_h_
+
+#define INT32_MIN (0x80000000)
+#ifndef INT32_MAX //INT32_MAX->Already defined
+#define INT32_MAX (0x7FFFFFFF)
+#endif
+#define INT16_MIN (0x8000)
+#define INT16_MAX (0x7FFF)
+
+///
+/// System boot mode.
+///
+typedef enum {
+ bmCold, ///< Cold boot
+ bmWarm, ///< Warm boot
+ bmS3, ///< S3 resume
+ bmFast, ///< Fast boot
+ MrcBootModeMax, ///< MRC_BOOT_MODE enumeration maximum value.
+ MrcBootModeDelim = INT32_MAX ///< This value ensures the enum size is consistent on both sides of the PPI.
+} MrcBootMode;
+
+///
+/// DIMM memory package
+/// This enum matches SPD Module Type - SPD byte 3, bits [3:0]
+/// Note that DDR3 and DDR4 have different encoding for some module types
+///
+typedef enum {
+ RDimmMemoryPackage = 1,
+ UDimmMemoryPackage = 2,
+ SoDimmMemoryPackage = 3,
+ MicroDimmMemoryPackageDdr3 = 4,
+ LrDimmMemoryPackageDdr4 = 4,
+ MiniRDimmMemoryPackage = 5,
+ MiniUDimmMemoryPackage = 6,
+ MiniCDimmMemoryPackage = 7,
+ LpDimmMemoryPackage = 7,
+ SoUDimmEccMemoryPackageDdr3 = 8,
+ SoRDimmEccMemoryPackageDdr4 = 8,
+ SoRDimmEccMemoryPackageDdr3 = 9,
+ SoUDimmEccMemoryPackageDdr4 = 9,
+ SoCDimmEccMemoryPackage = 10,
+ LrDimmMemoryPackage = 11,
+ SoDimm16bMemoryPackage = 12,
+ SoDimm32bMemoryPackage = 13,
+ NonDimmMemoryPackage = 14,
+ MemoryPackageMax, ///< MEMORY_PACKAGE enumeration maximum value.
+ MemoryPackageDelim = INT32_MAX ///< This value ensures the enum size is consistent on both sides of the PPI.
+} MEMORY_PACKAGE;
+
+///
+/// Memory training I/O levels.
+///
+typedef enum {
+ DdrLevel = 0, ///< Refers to frontside of DIMM
+ LrbufLevel = 1, ///< Refers to data level at backside of LRDIMM or AEP buffer
+ RegALevel = 2, ///< Refers to cmd level at backside of register - side A
+ RegBLevel = 3, ///< Refers to cmd level at backside of register - side B
+ GsmLtMax, ///< GSM_LT enumeration maximum value.
+ GsmLtDelim = INT32_MAX ///< This value ensures the enum size is consistent on both sides of the PPI.
+} GSM_LT;
+
+///
+/// Memory training margin group selectors.
+///
+typedef enum {
+ RecEnDelay = 0, ///< Linear delay (PI ticks), where the positive increment moves the RCVEN sampling window later in time relative to the RX DQS strobes.
+ RxDqsDelay = 1, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS strobe later in time relative to the RX DQ signal (i.e. toward the hold side of the eye).
+ RxDqDelay = 2, ///< Linear delay (PI ticks), where the positive increment moves the RX DQ byte/nibble/bitlane later in time relative to the RX DQS signal (i.e.closing the gap between DQ and DQS in the setup side of the eye).
+ RxDqsPDelay = 3, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS strobe for "even" chunks later in time relative to the RX DQ signal. Even chunks are 0, 2, 4, 6 within the 0 to 7 chunks of an 8 burst length cacheline, for example.
+ RxDqsNDelay = 4, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS strobe for "odd" chunks later in time relative to the RX DQ signal. Odd chunks are 1, 3, 5, 7 within the 0 to 7 chunks of an 8 burst length cacheline, for example.
+ RxVref = 5, ///< Linear increment (Vref ticks), where the positive increment moves the byte/nibble/bitlane RX Vref to a higher voltage.
+ RxEq = 6, ///< RX CTLE setting indicating a set of possible resistances, capacitance, current steering, etc. values, which may be a different set of values per product. The setting combinations are indexed by integer values.
+ RxDqBitDelay = 7, ///< Linear delay (PI ticks), where the positive increment moves the RX DQ bitlane later in time relative to the RX DQS signal (i.e.closing the gap between DQ and DQS in the setup side of the eye).
+ RxVoc = 8, ///< Monotonic increment (Sense Amp setting), where the positive increment moves the byte/nibble/bitlane's effective switching point to a lower Vref value.
+ RxOdt = 9, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ RxOdtUp = 10, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ RxOdtDn = 11, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ DramDrvStr = 12, ///< Drive strength setting resistance setting within a set of possible resistances (or currents), which may be a different set of values per product. Indexed by integer values.
+ McOdtDelay = 13, ///<
+ McOdtDuration = 14, ///<
+ SenseAmpDelay = 15, ///< This may be used to indicate CmdToDiffAmpEn for SoC's.
+ SenseAmpDuration = 16, ///<
+ RoundTripDelay = 17, ///< This may be used to indicate CmdToRdDataValid for SoC's.
+ RxDqsBitDelay = 18, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS within the bitlane later in time relative to the RX DQ signal (i.e.closing the gap between DQ and DQS in the hold side of the eye).
+ RxDqDqsDelay = 19, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS per strobe later in time relative to the RX DQ signal (i.e. closing the gap between DQS and DQ in the hold side of the eye. The difference between this parameter and RxDqsDelay is that both the DQ and DQS timings may be moved in order to increase the total range of DQDQS timings.
+ WrLvlDelay = 20, ///< Linear delay (PI ticks), where the positive increment moves both the TX DQS and TX DQ signals later in time relative to all other bus signals.
+ TxDqsDelay = 21, ///< Linear delay (PI ticks), where the positive increment moves the TX DQS strobe later in time relative to all other bus signals.
+ TxDqDelay = 22, ///< Linear delay (PI ticks), where the positive increment moves the TX DQ byte/nibble/bitlane later in time relative to all other bus signals.
+ TxVref = 23, ///< Linear increment (Vref ticks), where the positive increment moves the byte/nibble/bitlane TX Vref to a higher voltage. (Assuming this will abstract away from the range specifics for DDR4, for example.)
+ TxEq = 24, ///< TX EQ setting indicating a set of possible equalization levels, which may be a different set of values per product. The setting combinations are indexed by integer values.
+ TxDqBitDelay = 25, ///< Linear delay (PI ticks), where the positive increment moves the TX DQ bitlane later in time relative to all other bus signals.
+ TxRon = 26, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ TxRonUp = 27, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ TxRonDn = 28, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ TxSlewRate = 29, ///< Monotonic increment, where the positive increment moves the byte/nibble/bitlane's effective slew rate to a higher slope.
+ TxImode = 30, ///< TX I-Mode Boost setting indicating a set of possible current boost levels, which may be a different set of values per product. The setting combinations are indexed by integer values.
+ WrOdt = 31, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ NomOdt = 32, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ ParkOdt = 33, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+ TxTco = 34, ///<
+ RxCtleR = 36, ///<
+ RxCtleC = 37, ///<
+ RxDqsPBitDelay = 38, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS bitlane timing for "even" chunks later in time relative to the RX DQ bitlane signal. Even chunks are 0, 2, 4, 6 within the 0 to 7 chunks of an 8 burst length cacheline, for example.
+ RxDqsNBitDelay = 39, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS bitlane timing for "odd" chunks later in time relative to the RX DQ bitlane signal. Odd chunks are 1, 3, 5, 7 within the 0 to 7 chunks of an 8 burst length cacheline, for example.
+ CmdAll = 40, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CMD_ALL category later in time relative to all other signals on the bus.
+ CmdGrp0 = 41, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CMD_GRP0 category later in time relative to all other signals on the bus.
+ CmdGrp1 = 42, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CMD_GRP1 category later in time relative to all other signals on the bus.
+ CmdGrp2 = 43, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CMD_GRP2 category later in time relative to all other signals on the bus.
+ CtlAll = 44, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CTL_ALL category later in time relative to all other signals on the bus.
+ CtlGrp0 = 45, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CTL_GRP0 category later in time relative to all other signals on the bus.
+ CtlGrp1 = 46, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CTL_GRP1 category later in time relative to all other signals on the bus.
+ CtlGrp2 = 47, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CTL_GRP2 category later in time relative to all other signals on the bus.
+ CtlGrp3 = 48, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CTL_GRP3 category later in time relative to all other signals on the bus.
+ CtlGrp4 = 49, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CTL_GRP4 category later in time relative to all other signals on the bus.
+ CtlGrp5 = 50, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CTL_GRP5 category later in time relative to all other signals on the bus.
+ CmdCtlAll = 51, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CMD_CTL_ALL category later in time relative to all other signals on the bus.
+ CkAll = 52, ///< Linear delay (PI ticks), where the positive increment moves all signals assigned to the CK_ALL category later in time relative to all other signals on the bus.
+ CmdVref = 53, ///< Linear increment (Vref ticks), where the positive increment moves the CMD Vref to a higher voltage.
+ AlertVref = 54, ///< Linear increment (Vref ticks), where the positive increment moves the ALERT Vref to a higher voltage.
+ CmdRon = 55, ///< Resistance setting within a set of possible resistances, which may be a different set of values per product. Indexed by integer values.
+
+ EridDelay = 60, ///< Linear delay (PI ticks), where the positive increment moves the ERID signals later in time relative to the internal sampling clock (i.e.closing the gap between ERID and internal sampling clock in the setup side of the eye). This group is applicable for DDRT DIMMs.
+ EridVref = 61, ///< Linear increment (Vref ticks), where the positive increment moves the ERID Vref to a higher voltage. This group is applicable for DDRT DIMMs.
+ ErrorVref = 62, ///< Linear increment (Vref ticks), where the positive increment moves the ERROR Vref to a higher voltage. This group is applicable for DDRT DIMMs.
+ ReqVref = 63, ///< Linear increment (Vref ticks), where the positive increment moves the REQ Vref to a higher voltage. This group is applicable for DDRT DIMMs.
+ RecEnOffset = 64, ///< Linear delay (PI ticks), where the positive increment moves the RCVEN sampling window later in time relative to the RX DQS strobes.
+ RxDqsOffset = 65, ///< Linear delay (PI ticks), where the positive increment moves the RX DQS strobe later in time relative to the RX DQ signal (i.e. toward the hold side of the eye).
+ RxVrefOffset = 66, ///< Linear increment (Vref ticks), where the positive increment moves the byte/nibble/bitlane RX Vref to a higher voltage.
+ TxDqsOffset = 67, ///< Linear delay (PI ticks), where the positive increment moves the TX DQS strobe later in time relative to all other bus signals.
+ TxDqOffset = 68, ///< Linear delay (PI ticks), where the positive increment moves the TX DQ byte/nibble/bitlane later in time relative to all other bus signals.
+ GsmGtMax, ///< SSA_GSM_GT enumeration maximum value.
+ GsmGtDelim = INT32_MAX ///< This value ensures the enum size is consistent on both sides of the PPI.
+} GSM_GT;
+
+typedef enum {
+ SigRasN = 0,
+ SigCasN = 1,
+ SigWeN = 2,
+ SigBa0 = 3,
+ SigBa1 = 4,
+ SigBa2 = 5,
+ SigA0 = 6,
+ SigA1 = 7,
+ SigA2 = 8,
+ SigA3 = 9,
+ SigA4 = 10,
+ SigA5 = 11,
+ SigA6 = 12,
+ SigA7 = 13,
+ SigA8 = 14,
+ SigA9 = 15,
+ SigA10 = 16,
+ SigA11 = 17,
+ SigA12 = 18,
+ SigA13 = 19,
+ SigA14 = 20,
+ SigA15 = 21,
+ SigA16 = 22,
+ SigA17 = 23,
+ SigCs0N = 24,
+ SigCs1N = 25,
+ SigCs2N = 26,
+ SigCs3N = 27,
+ SigCs4N = 28,
+ SigCs5N = 29,
+ SigCs6N = 30,
+ SigCs7N = 31,
+ SigCs8N = 32,
+ SigCs9N = 33,
+ SigCke0 = 34,
+ SigCke1 = 35,
+ SigCke2 = 36,
+ SigCke3 = 37,
+ SigCke4 = 38,
+ SigCke5 = 39,
+ SigOdt0 = 40, //could also be used for CA-ODT for LP4
+ SigOdt1 = 41, //could also be used for CA-ODT for LP4
+ SigOdt2 = 42,
+ SigOdt3 = 43,
+ SigOdt4 = 44,
+ SigOdt5 = 45,
+ SigPar = 46,
+ SigAlertN = 47,
+ SigBg0 = 48,
+ SigBg1 = 49,
+ SigActN = 50,
+ SigCid0 = 51,
+ SigCid1 = 52,
+ SigCid2 = 53,
+ SigCk0 = 54,
+ SigCk1 = 55,
+ SigCk2 = 56,
+ SigCk3 = 57,
+ SigCk4 = 58,
+ SigCk5 = 59,
+ SigGnt0 = 60,
+ SigGnt1 = 61,
+ SigErid00 = 62,
+ SigErid01 = 63,
+ SigErid10 = 64,
+ SigErid11 = 65,
+ SigErr0 = 66,
+ SigErr1 = 67,
+ SigCa00 = 68, // First instantiation of the CA bus for a given channel
+ SigCa01 = 69,
+ SigCa02 = 70,
+ SigCa03 = 71,
+ SigCa04 = 72,
+ SigCa05 = 73,
+ SigCa10 = 74, // Second instantiation of the CA bus for a given channel
+ SigCa11 = 75,
+ SigCa12 = 76,
+ SigCa13 = 77,
+ SigCa14 = 78,
+ SigCa15 = 79,
+ GsmCsnMax,
+ GsmCsnDelim = INT32_MAX
+} GSM_CSN;
+
+
+#endif // _MrcCommonTypes_h_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcInterface.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcInterface.h
new file mode 100644
index 0000000000..87ad005f03
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcInterface.h
@@ -0,0 +1,1756 @@
+/** @file
+ This file includes all the data structures that the MRC considers "global data".
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MrcInterface_h_
+#define _MrcInterface_h_
+#include "MrcTypes.h"
+#include "ConfigBlock.h"
+
+#define MAX_CPU_SOCKETS (1) ///< The maximum number of CPUs per system.
+#define MAX_CONTROLLERS (1) ///< The maximum number of memory controllers per CPU socket.
+#define MAX_CHANNEL (2) ///< The maximum number of channels per memory controller.
+#define MAX_DIMMS_IN_CHANNEL (2) ///< The maximum number of DIMMs per channel.
+#define MAX_RANK_IN_DIMM (2) ///< The maximum number of ranks per DIMM.
+#define MAX_RANK_IN_CHANNEL (MAX_DIMMS_IN_CHANNEL * MAX_RANK_IN_DIMM) ///< The maximum number of ranks per channel.
+#define MAX_SDRAM_IN_DIMM (9) ///< The maximum number of SDRAMs per DIMM when ECC is enabled.
+#define MAX_MR_IN_DIMM (7) ///< Maximum number of mode registers in a DIMM.
+#define MAX_DEVICES_IN_DDR4 (8) ///< The maximum number of SDRAMs per DDR4 DIMM.
+#define MAX_BITS (8) ///< BITS per byte.
+#define MAX_STROBE (18) ///< Number of strobe groups.
+#define MAX_DQ (72) ///< Number of Dq bits used by the rank.
+#define CHAR_BITS (8) ///< Number of bits in a char.
+#define PSMI_SIZE_MB (64) ///< Define the max size of PSMI needed in MB
+#define BCLK_DEFAULT (100 * 1000 * 1000) ///< BCLK default value, in Hertz.
+#define MAX_COMMAND_GROUPS (2)
+#define MAX_EDGES (2) ///< Maximum number of edges.
+#define SUPPORT_DDR3 SUPPORT ///< SUPPORT means that DDR3 is supported by the MRC.
+#define ULT_SUPPORT_LPDDR3 SUPPORT ///< SUPPORT means that LPDDR3 is supported by the MRC.
+#define TRAD_SUPPORT_LPDDR3 /*UN*/SUPPORT ///< SUPPORT means that LPDDR3 is supported by the MRC.
+#define BDW_SUPPORT_LPDDR3 SUPPORT ///< SUPPORT means that LPDDR3 is supported by the MRC.
+#define JEDEC_SUPPORT_LPDDR SUPPORT ///< SUPPORT means that JEDEC SPD Spec for LPDDR3 is supported by the MRC.
+#define SUPPORT_DDR4 SUPPORT ///< SUPPORT means that DDR4 is supported by the MRC.
+#define SUPPORT_LPDDR3 (ULT_SUPPORT_LPDDR3 || TRAD_SUPPORT_LPDDR3 || BDW_SUPPORT_LPDDR3 || JEDEC_SUPPORT_LPDDR)
+#define MRC_ALL_DDR_SUPPORTED ((SUPPORT_DDR4 == SUPPORT) && ((SUPPORT_DDR3 == SUPPORT) && (SUPPORT_LPDDR3 == SUPPORT)))
+#define MRC_DDR3_LPDDR_SUPPORTED ((SUPPORT_DDR3 == SUPPORT) || (SUPPORT_LPDDR3 == SUPPORT))
+#define SPD3_MANUF_START 117 ///< The starting point for the SPD manufacturing data.
+#define SPD3_MANUF_END 127 ///< The ending point for the SPD manufacturing data.
+#if (SUPPORT_DDR4 == SUPPORT)
+#define SPD4_MANUF_START 320 ///< The starting point for the SPD manufacturing data.
+#define SPD4_MANUF_END 328 ///< The ending point for the SPD manufacturing data.
+#endif
+#if (JEDEC_SUPPORT_LPDDR == SUPPORT)
+#define SPDLP_MANUF_START 320 ///< The starting point for the SPD manufacturing data.
+#define SPDLP_MANUF_END 328 ///< The ending point for the SPD manufacturing data.
+#endif
+
+#include "CpuRegs.h"
+#include "MrcSpdData.h"
+#include "MrcRmtData.h"
+#include "MrcCommonTypes.h"
+#pragma pack (push, 1)
+
+
+///
+//////////////////////////////////////////////////////////////////////////////////////
+/// OEM platform routines and types //
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// define the oem check points the OEM can define more point and locate them in the code.
+///
+typedef enum {
+ OemFastBootPermitted, ///< before fast boot.
+ OemRestoreNonTraining,
+ OemPrintInputParameters, ///< before printing input parameters
+ OemSpdProcessingRun, ///< before spd processing code
+ OemSetOverridePreSpd, ///< before set overrides pre spd
+ OemSetOverride, ///< before set overrides
+ OemMcCapability, ///< before MC capability
+ OemMcInitRun, ///< before mc init code
+ OemMcMemoryMap, ///< before memory map
+ OemMcResetRun, ///< before jedec reset
+ OemPreTraining, ///< before the training.
+ OemMcTrainingRun, ///< before training code
+ OemEarlyCommandTraining, ///< before Early Command training
+ OemJedecInitLpddr3, ///< before Jedec Init Lpddr3
+ OemSenseAmpTraining, ///< before Sense Amp Training
+ OemReadMprTraining, ///< before Read MPR Training
+ OemReceiveEnable, ///< before Read Leveling
+ OemJedecWriteLeveling, ///< before Jedec Write Leveling
+ OemLpddrLatencySetB, ///< before LPDDR Latency Set B
+ OemWriteDqDqs, ///< before Write Timing Centering
+ OemWriteVoltage, ///< before Write Voltage Centering
+ OemEarlyWriteDqDqs2D, ///< before Early Write Timing Centering 2D
+ OemEarlyWrDsEq, ///< before Early Write Drive Strength / Equalization
+ OemEarlyReadDqDqs2D, ///< before Early Read Timing Centering 2D
+ OemEarlyReadMprDqDqs2D, ///< before Early MPR Read Timing Centering 2D
+ OemReadDqDqs, ///< before Read Timing Centering
+ OemDdr4Map, ///< before DDR4 PDA Mapping
+ OemDimmRonTraining, ///< before DIMM Ron Training
+ OemDimmODTTraining, ///< before DIMM ODT Training
+ OemWriteDriveStrengthEq, ///< before Write Drive Strength/Equalization 2D Training
+ OemWriteDriveUpDn, ///< before Write Drive Strength Up/Dn 2D Training
+ OemWriteSlewRate, ///< before Write Slew Rate Training
+ OemReadODTTraining, ///< before Read ODT algorithm.
+ OemReadEQTraining, ///< before Read Equalization Training
+ OemReadAmplifierPower, ///< before Read Amplifier Power
+ OemOptimizeComp, ///< before Comp Optimization Training
+ OemPowerSavingMeter, ///< before PowerSavingMeter step
+ OemWriteDqDqs2D, ///< before Write Timing Centering 2D
+ OemReadDqDqs2D, ///< before Read Timing Centering 2D
+ OemCmdVoltCenterPreLct, ///< before Command Voltage Centering that runs pre-LCT
+ OemCmdSlewRate, ///< before CMD Slew Rate
+ OemCmdVoltCentering, ///< before Command Voltage Centering
+ OemCmdDriveStrengthEq, ///< before Command Drive Strength Equalization
+ OemWriteVoltCentering2D, ///< before Write Voltage Centering 2D
+ OemReadVoltCentering2D, ///< before Read Voltage Centering 2D
+ OemLateCommandTraining, ///< before Late Command training
+ OemCmdNormalization, ///< before CMD Normalization
+ OemRoundTripLatency, ///< before Round Trip Latency Traiing
+ OemTurnAroundTimes, ///< before Turn Aorund Times.
+ OemRcvEnCentering1D, ///< before Receive Enable Centring
+ OemSaveMCValues, ///< before saving memory controller values
+ OemRmt, ///< before RMT crosser tool.
+ OemMemTest, ///< before Memory testing
+ OemRestoreTraining, ///< before Restoring Training Values
+ OemJedecResetDdr4Fast, ///< before JEDEC reset for DDR4 in Fast flow
+ OemSelfRefreshExit, ///< before Self Refresh Exit
+ OemNormalMode, ///< before Normal Mode on non-cold boots.
+ OemTxtAliasCheck, ///< before TxT Alias Check Call.
+ OemAliasCheck, ///< before alias checking on cold boots.
+ OemHwMemInit,
+
+ OemPostTraining, ///< after the training.
+ OemForceOltm, ///< before MrcForceOltm
+ OemMrcActivate, ///< before MrcActivate call.
+ OemMrcRhPrevention, ///< before MrcRhPrevention
+ OemSaGvSwitch, ///< before SA GV switch
+ OemEngPerfGain, ///< before Energy Performance Gain.
+ OemMrcDone, ///< call to MrcOemCheckPoint when MRC was done.
+ OemFrequencySet, ///< do operation before frequency set.
+ OemFrequencySetDone, ///< do operation after frequency set.
+ OemStartMemoryConfiguration,
+ OemBeforeNormalMode, ///< call to MrcOemCheckPoint before normal mode is enalbed
+ OemAfterNormalMode, ///< call to MrcOemCheckPoint after normal mode is enalbed
+ OemMrcFillRmt,
+ OemRetrainMarginCheck,
+ OemSsaStopPoint, ///< Call to SSA stop point
+ ///
+ ///*********************************************************************************
+ ///
+ OemNumOfCommands ///< Should always be last in the list!
+} MrcOemStatusCommand;
+
+typedef UINT8 MrcIteration; ///< Mrc invocation sequence number, start with 0 and increment by one each time MRC library is called.
+#define MRC_ITERATION_MAX ((1 << ((sizeof (MrcIteration) * 8) - 1)) + ((1 << ((sizeof (MrcIteration) * 8) - 1)) - 1))
+
+#define MAX_RCOMP (3)
+#define MAX_RCOMP_TARGETS (5)
+
+///
+/// Thermal Options
+///
+typedef struct {
+ UINT8 RaplLim2WindX; ///< Offset 110 - Power Limit 2 Time Window X value: 0=Minimal, 3=Maximum, <b>1=Default</b>
+ UINT8 RaplLim2WindY; ///< Offset 111 - Power Limit 2 Time Window Y value: 0=Minimal, 3=Maximum, <b>1=Default</b>
+ UINT8 RaplLim1WindX; ///< Offset 112 - Power Limit 1 Time Window X value: <b>0=Minimal</b>, 3=Maximum
+ UINT8 RaplLim1WindY; ///< Offset 113 - Power Limit 1 Time Window Y value: <b>0=Minimal</b>, 31=Maximum
+ UINT16 RaplLim2Pwr; ///< Offset 114 - Power Limit 2: 0=Minimal, 16383=Maximum, <b>222=Default</b>
+ UINT16 RaplLim1Pwr; ///< Offset 116 - Power Limit 1: <b>0=Minimal</b>, 16383=Maximum
+ UINT8 WarmThreshold[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL]; ///< Offset 118 - Warm Threshold (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotThreshold[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL]; ///< Offset 122 - Hot Threshold (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 WarmBudget[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL]; ///< Offset 126 - Warm Budget (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 HotBudget[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL]; ///< Offset 130 - Hot Budget (Channel 0, Dimm 0): 0=Minimal, <b>255=Maximum</b>
+ UINT8 IdleEnergy[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL];
+ UINT8 PdEnergy[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL];
+ UINT8 ActEnergy[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL];
+ UINT8 RdEnergy[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL];
+ UINT8 WrEnergy[MAX_CHANNEL][MAX_DIMMS_IN_CHANNEL];
+} ThermalMngmtEn;
+
+
+typedef struct {
+ UINT8 GdxcEnable; ///< GDXC MOT enable
+ UINT8 GdxcIotSize; ///< IOT size in multiples of 8MEG
+ UINT8 GdxcMotSize; ///< MOT size in multiples of 8MEG
+} MrcGdxc;
+
+typedef struct {
+ UINT32 ECT : 1; ///< BIT0 - Early Command Training
+ UINT32 SOT : 1; ///< BIT1 - Sense Amp Offset Training
+ UINT32 ERDMPRTC2D : 1; ///< BIT2 - Early ReadMPR Timing Centering 2D
+ UINT32 RDMPRT : 1; ///< BIT3 - Read MPR Training
+ UINT32 RCVET : 1; ///< BIT4 - Read Leveling Training (RcvEn)
+ UINT32 JWRL : 1; ///< BIT5 - Jedec Write Leveling
+ UINT32 EWRTC2D : 1; ///< BIT6 - Early Write Time Centering 2D
+ UINT32 ERDTC2D : 1; ///< BIT7 - Early Read Time Centering 2D
+ UINT32 WRTC1D : 1; ///< BIT8 - Write Timing Centering 1D
+ UINT32 WRVC1D : 1; ///< BIT9 - Write Voltage Centering 1D
+ UINT32 RDTC1D : 1; ///< BIT10 - Read Timing Centering 1D
+ UINT32 DIMMODTT : 1; ///< BIT11 - Dimm ODT Training
+ UINT32 DIMMRONT : 1; ///< BIT12 - Dimm Ron Training
+ UINT32 WRDSEQT : 1; ///< BIT13 - Write Drive Strength / Equalization Training 2D
+ UINT32 WRSRT : 1; ///< BIT14 - Write Slew Rate Training
+ UINT32 RDODTT : 1; ///< BIT15 - Read ODT Training
+ UINT32 RDEQT : 1; ///< BIT16 - Read Equalization Training
+ UINT32 RDAPT : 1; ///< BIT17 - Read Amplifier Power Training
+ UINT32 WRTC2D : 1; ///< BIT18 - Write Timing Centering 2D
+ UINT32 RDTC2D : 1; ///< BIT19 - Read Timing Centering 2D
+ UINT32 WRVC2D : 1; ///< BIT20 - Write Voltage Centering 2D
+ UINT32 RDVC2D : 1; ///< BIT21 - Read Voltage Centering 2D
+ UINT32 CMDVC : 1; ///< BIT22 - Command Voltage Centering
+ UINT32 LCT : 1; ///< BIT23 - Late Command Training
+ UINT32 RTL : 1; ///< BIT24 - Round Trip latency
+ UINT32 TAT : 1; ///< BIT25 - Turn Around Timing
+ UINT32 RMT : 1; ///< BIT26 - RMT Tool
+ UINT32 MEMTST : 1; ///< BIT27 - Memory Test
+ UINT32 ALIASCHK: 1; ///< BIT28 - SPD Alias Check
+ UINT32 RCVENC1D: 1; ///< BIT29 - Receive Enable Centering 1D
+ UINT32 RMC : 1; ///< BIT30 - Retrain Margin Check
+ UINT32 WRDSUDT : 1; ///< BIT31 - Write Drive Strength Up/Dn independently
+} TrainingStepsEn;
+
+typedef struct {
+ UINT32 CMDSR : 1; ///< BIT0 - CMD Slew Rate Training
+ UINT32 CMDDSEQ : 1; ///< BIT1 - CMD Drive Strength and Tx Equalization
+ UINT32 CMDNORM : 1; ///< BIT2 - CMD Normalization
+ UINT32 EWRDSEQ : 1; ///< BIT3 - Early DQ Write Drive Strength and Equalization Training
+ UINT32 RsvdBits :28;
+} TrainingStepsEn2;
+
+///
+/// Defines whether the MRC is executing in full or mini BIOS mode.
+///
+typedef enum {
+ MrcModeFull, ///< Select full BIOS MRC execution.
+ MrcModeMini, ///< Select mini BIOS MRC execution.
+ MrcModeMaximum ///< Delimiter.
+} MrcMode;
+
+typedef enum {
+ MrcTmPower,
+ MrcTmMargin,
+ MrcTmMax
+} TrainingModeType;
+
+typedef enum {
+ LastRxV,
+ LastRxT,
+ LastTxV,
+ LastTxT,
+ LastRcvEna,
+ LastWrLevel,
+ LastCmdT,
+ LastCmdV,
+ MAX_RESULT_TYPE
+} MrcMarginResult;
+
+typedef enum {
+ MSG_LEVEL_NEVER,
+ MSG_LEVEL_ERROR,
+ MSG_LEVEL_WARNING,
+ MSG_LEVEL_NOTE,
+ MSG_LEVEL_EVENT,
+ MSG_LEVEL_ALGO,
+ MSG_LEVEL_MMIO,
+ MSG_LEVEL_CSV,
+ MSG_LEVEL_TIME,
+ MSG_LEVEL_ALL = MRC_INT32_MAX
+} MrcDebugMsgLevel;
+
+///
+/// Define the frequencies that may be possible in the memory controller.
+/// Note that not all these values may be supported.
+///
+#define fNoInit (0)
+#define f800 (800)
+#define f1000 (1000)
+#define f1100 (1100)
+#define f1067 (1067)
+#define f1200 (1200)
+#define f1300 (1300)
+#define f1333 (1333)
+#define f1400 (1400)
+#define f1467 (1467)
+#define f1500 (1500)
+#define f1600 (1600)
+#define f1700 (1700)
+#define f1733 (1733)
+#define f1800 (1800)
+#define f1867 (1867)
+#define f1900 (1900)
+#define f2000 (2000)
+#define f2100 (2100)
+#define f2133 (2133)
+#define f2200 (2200)
+#define f2267 (2267)
+#define f2300 (2300)
+#define f2400 (2400)
+#define f2500 (2500)
+#define f2533 (2533)
+#define f2600 (2600)
+#define f2667 (2667)
+#define f2700 (2700)
+#define f2800 (2800)
+#define f2900 (2900)
+#define f2933 (2933)
+#define f3000 (3000)
+#define f3067 (3067)
+#define f3100 (3100)
+#define f3200 (3200)
+#define f3333 (3333)
+#define f3467 (3467)
+#define f3600 (3600)
+#define f3733 (3733)
+#define f3867 (3867)
+#define f4000 (4000)
+#define f4133 (4133)
+#define fInvalid (0x7FFFFFFF)
+typedef UINT32 MrcFrequency;
+
+//
+// Max supported frequency in OC mode
+// RefClk133: 15*266 + 100 = 4133 (using Odd ratio mode)
+// RefClk100: 15*200 + 100 = 3100 (using Odd ratio mode)
+//
+#define MAX_FREQ_OC_133 f4133
+#define MAX_FREQ_OC_100 f3100
+
+//
+// tCK value in femtoseconds for various frequencies
+// If Freq is in MHz, then tCK[fs] = 10^9 * 1/(Freq/2)
+//
+#define MRC_DDR_800_TCK_MIN 2500000
+#define MRC_DDR_1000_TCK_MIN 2000000
+#define MRC_DDR_1067_TCK_MIN 1875000
+#define MRC_DDR_1100_TCK_MIN 1818182
+#define MRC_DDR_1200_TCK_MIN 1666667
+#define MRC_DDR_1300_TCK_MIN 1538462
+#define MRC_DDR_1333_TCK_MIN 1500000
+#define MRC_DDR_1400_TCK_MIN 1428571
+#define MRC_DDR_1467_TCK_MIN 1363636
+#define MRC_DDR_1500_TCK_MIN 1333333
+#define MRC_DDR_1600_TCK_MIN 1250000
+#define MRC_DDR_1700_TCK_MIN 1176471
+#define MRC_DDR_1733_TCK_MIN 1153846
+#define MRC_DDR_1800_TCK_MIN 1111111
+#define MRC_DDR_1867_TCK_MIN 1071429
+#define MRC_DDR_1900_TCK_MIN 1052632
+#define MRC_DDR_2000_TCK_MIN 1000000
+#define MRC_DDR_2100_TCK_MIN 952381
+#define MRC_DDR_2133_TCK_MIN 938000
+#define MRC_DDR_2200_TCK_MIN 909091
+#define MRC_DDR_2267_TCK_MIN 882353
+#define MRC_DDR_2300_TCK_MIN 869565
+#define MRC_DDR_2400_TCK_MIN 833333
+#define MRC_DDR_2500_TCK_MIN 800000
+#define MRC_DDR_2533_TCK_MIN 789474
+#define MRC_DDR_2600_TCK_MIN 769231
+#define MRC_DDR_2667_TCK_MIN 750000
+#define MRC_DDR_2700_TCK_MIN 740741
+#define MRC_DDR_2800_TCK_MIN 714286
+#define MRC_DDR_2900_TCK_MIN 689655
+#define MRC_DDR_2933_TCK_MIN 681818
+#define MRC_DDR_3000_TCK_MIN 666667
+#define MRC_DDR_3067_TCK_MIN 652174
+#define MRC_DDR_3100_TCK_MIN 645161
+#define MRC_DDR_3200_TCK_MIN 625000
+#define MRC_DDR_3333_TCK_MIN 600000
+#define MRC_DDR_3467_TCK_MIN 576923
+#define MRC_DDR_3600_TCK_MIN 555556
+#define MRC_DDR_3733_TCK_MIN 535714
+#define MRC_DDR_3867_TCK_MIN 517241
+#define MRC_DDR_4000_TCK_MIN 500000
+#define MRC_DDR_4133_TCK_MIN 483871
+
+///
+/// Define the memory nominal voltage (VDD).
+/// Note that not all these values may be supported.
+///
+typedef enum {
+ VDD_INVALID,
+ VDD_1_00 = 1000,
+ VDD_1_05 = 1050,
+ VDD_1_10 = 1100,
+ VDD_1_15 = 1150,
+ VDD_1_20 = 1200,
+ VDD_1_25 = 1250,
+ VDD_1_30 = 1300,
+ VDD_1_35 = 1350,
+ VDD_1_40 = 1400,
+ VDD_1_45 = 1450,
+ VDD_1_50 = 1500,
+ VDD_1_55 = 1550,
+ VDD_1_60 = 1600,
+ VDD_1_65 = 1650,
+ VDD_1_70 = 1700,
+ VDD_1_75 = 1750,
+ VDD_1_80 = 1800,
+ VDD_1_85 = 1850,
+ VDD_1_90 = 1900,
+ VDD_1_95 = 1950,
+ VDD_2_00 = 2000,
+ VDD_2_05 = 2050,
+ VDD_2_10 = 2100,
+ VDD_2_15 = 2150,
+ VDD_2_20 = 2200,
+ VDD_2_25 = 2250,
+ VDD_2_30 = 2300,
+ VDD_2_35 = 2350,
+ VDD_2_40 = 2400,
+ VDD_2_45 = 2450,
+ VDD_2_50 = 2500,
+ VDD_2_55 = 2550,
+ VDD_2_60 = 2600,
+ VDD_2_65 = 2650,
+ VDD_2_70 = 2700,
+ VDD_2_75 = 2750,
+ VDD_2_80 = 2800,
+ VDD_2_85 = 2850,
+ VDD_2_90 = 2900,
+ VDD_2_95 = 2950,
+ VDD_MAXIMUM = 0x7FFFFFFF
+} MrcVddSelect;
+
+///
+/// SA GV points
+///
+typedef enum {
+ MrcSaGvPointLow,
+ MrcSaGvPointHigh,
+} MrcSaGvPoint;
+
+///
+/// SA GV modes
+/// Disabled: SA GV Disabled, run all MRC tasks
+/// FixedLow: SA GV Disabled, run only MRC tasks marked with MRC_PF_GV_LOW
+/// FixedHigh: SA GV Disabled, run only MRC tasks marked with MRC_PF_GV_HIGH
+/// Enabled: SA GV Enabled
+///
+typedef enum {
+ MrcSaGvDisabled,
+ MrcSaGvFixedLow,
+ MrcSaGvFixedHigh,
+ MrcSaGvEnabled,
+} MrcSaGv;
+
+///
+/// DIMM SPD Security Status
+///
+typedef enum {
+ MrcSpdStatusGood, ///< Memory is in a secure state.
+ MrcSpdStatusAliased, ///< Memory is aliased.
+ MrcSpdStatusLast ///< Must be last in the list
+} MrcSpdStatus;
+
+///
+/// Define the virtual channel.
+///
+typedef enum {
+ vcL, ///< Virtual channel L
+ vcS, ///< Virtual channel S
+} MrcVirtualChannel;
+
+///
+/// Define the board types.
+///
+typedef enum {
+ btCRBMB, ///< 0 - CRB Mobile
+ btCRBDT, ///< 1 - CRB Desktop
+ btUser1, ///< 2 - SV mobile
+ btUser2, ///< 3 - SV desktop
+ btUser3, ///< 4 - SV server?
+ btUser4, ///< 5 - Ult
+ btCRBEMB, ///< 6 - CRB Embedded
+ btUpServer, ///< 7 - Up Server
+ btUnknown, ///< 8 - Unknown
+ btMaximum ///< Delimiter
+} MrcBoardType;
+
+///
+/// Define the CPU family/model.
+///
+typedef enum {
+ cmSKL_ULX_ULT = CPUID_FULL_FAMILY_MODEL_SKYLAKE_ULT_ULX, ///< Skylake ULT/ULX
+ cmSKL_DT_HALO = CPUID_FULL_FAMILY_MODEL_SKYLAKE_DT_HALO, ///< Skylake DT/Halo
+ cmKBL_ULX_ULT = CPUID_FULL_FAMILY_MODEL_KABYLAKE_ULT_ULX, ///< Kabylake ULT/ULX
+ cmKBL_DT_HALO = CPUID_FULL_FAMILY_MODEL_KABYLAKE_DT_HALO ///< Kabylake DT/Halo
+} MrcCpuModel;
+
+///
+/// Define the CPU Tick/Tock.
+///
+typedef enum {
+ cfSkl = 0, ///< Skylake
+ cfKbl, ///< Kabylake
+ cfMax
+} MrcCpuFamily;
+
+///
+/// Define the CPU stepping number.
+///
+typedef enum {
+ ///
+ /// Skylake ULX/ULT
+ ///
+ csSklB0 = EnumSklB0,
+ csSklJ0 = EnumSklJ0,
+ csSklC0 = EnumSklC0,
+ csSklK0 = EnumSklK0,
+ csSklD0 = EnumSklD0,
+ csSklUlxUltLast = csSklD0,
+
+ ///
+ /// Kabylake ULX/ULT
+ ///
+ csKblG0 = EnumKblG0,
+ csKblH0 = EnumKblH0,
+ csKblJ0 = EnumKblJ0,
+ csKblY0 = EnumKblY0,
+ csKblUlxUltLast = csKblY0,
+
+ ///
+ /// Skylake DT/Halo
+ ///
+ csSklP0 = EnumSklP0,
+ csSklQ0 = EnumSklQ0,
+ csSklM0 = EnumSklM0,
+ csSklR0 = EnumSklR0,
+ csSklS0 = EnumSklS0,
+ csSklN0 = EnumSklN0,
+ csSklDtHaloLast = csSklN0,
+
+ ///
+ /// Kabylake DT/Halo
+ ///
+ csKblA0 = EnumKblA0,
+ csKblB0 = EnumKblB0,
+ csKblS0 = EnumKblS0,
+ csKblM0 = EnumKblM0,
+ csKblN0 = EnumKblN0,
+ csKblDtHaloLast = csKblN0,
+} MrcCpuStepping;
+
+typedef enum {
+ CONTROLLER_NOT_PRESENT, ///< There is no controller present in the system.
+ CONTROLLER_DISABLED, ///< There is a controller present but it is disabled.
+ CONTROLLER_PRESENT, ///< There is a controller present and it is enabled.
+ MAX_CONTROLLER_STATUS ///< Delimiter
+} MrcControllerSts;
+
+typedef enum {
+ CHANNEL_NOT_PRESENT, ///< There is no channel present on the controller.
+ CHANNEL_DISABLED, ///< There is a channel present but it is disabled.
+ CHANNEL_PRESENT, ///< There is a channel present and it is enabled.
+ MAX_CHANNEL_STATUS ///< Delimiter
+} MrcChannelSts;
+
+typedef enum {
+ DIMM_ENABLED, ///< DIMM/rank Pair is enabled, presence will be detected.
+ DIMM_DISABLED, ///< DIMM/rank Pair is disabled, regardless of presence.
+ DIMM_PRESENT, ///< There is a DIMM present in the slot/rank pair and it will be used.
+ DIMM_NOT_PRESENT, ///< There is no DIMM present in the slot/rank pair.
+ MAX_DIMM_STATUS ///< Delimiter
+} MrcDimmSts;
+
+typedef enum {
+ STD_PROFILE, ///< Standard DIMM profile select.
+ USER_PROFILE, ///< User specifies various override values.
+ XMP_PROFILE1, ///< XMP enthusiast settings select (XMP profile #1).
+ XMP_PROFILE2, ///< XMP extreme settings select (XMP profile #2).
+ MAX_PROFILE ///< Delimiter
+} MrcProfile;
+
+#define XMP_PROFILES_ENABLE (0x3)
+#define XMP1_PROFILE_ENABLE (0x1)
+#define XMP2_PROFILE_ENABLE (0x2)
+
+typedef enum {
+ MRC_REF_CLOCK_133, ///< 133MHz reference clock
+ MRC_REF_CLOCK_100, ///< 100MHz reference clock
+ MRC_REF_CLOCK_MAXIMUM ///< Delimiter
+} MrcRefClkSelect; ///< This value times the MrcClockRatio determines the MrcFrequency.
+
+typedef enum {
+ MRC_FREQ_INVALID = 0,
+ MRC_FREQ_133 = (MRC_BIT0 << MRC_REF_CLOCK_133), // Bit 0
+ MRC_FREQ_100 = (MRC_BIT0 << MRC_REF_CLOCK_100), // Bit 1
+ MRC_FREQ_133_ODD_RATIO = (MRC_BIT2 << MRC_REF_CLOCK_133), // Bit 2
+ MRC_FREQ_100_ODD_RATIO = (MRC_BIT2 << MRC_REF_CLOCK_100), // Bit 3
+ MRC_FREQ_MAX // Delimiter
+} MrcFreqFlag;
+
+typedef UINT32 MrcBClkRef; ///< Base clock, in Hertz, Default is 100MHz or leave at zero for default.
+
+//
+// This encoding matches SKL SC_GS_CFG.DRAM_technology and MAD_INTER_CHANNEL.DDR_TYPE registers
+//
+typedef enum {
+ MRC_DDR_TYPE_DDR4 = 0,
+ MRC_DDR_TYPE_DDR3 = 1,
+ MRC_DDR_TYPE_LPDDR3 = 2,
+ MRC_DDR_TYPE_UNKNOWN = 3,
+ MAX_MRC_DDR_TYPE ///< Delimiter
+} MrcDdrType;
+
+typedef enum {
+ MrcIterationClock,
+ MrcIterationCmdN,
+ MrcIterationCmdS,
+ MrcIterationCke,
+ MrcIterationCtl,
+ MrcIterationCmdV,
+ MrcIterationMax
+} MrcIterationType;
+
+typedef enum {
+ UpmLimit,
+ PowerLimit,
+ RetrainLimit,
+ MarginLimitMax
+} MRC_MARGIN_LIMIT_TYPE;
+
+
+typedef enum {
+ HardwareRhp,
+ Refresh2x
+} MrcRhpType;
+
+typedef enum {
+ OneIn2To1 = 1,
+ OneIn2To2,
+ OneIn2To3,
+ OneIn2To4,
+ OneIn2To5,
+ OneIn2To6,
+ OneIn2To7,
+ OneIn2To8,
+ OneIn2To9,
+ OneIn2To10,
+ OneIn2To11,
+ OneIn2To12,
+ OneIn2To13,
+ OneIn2To14,
+ OneIn2To15
+} MrcRhProbType;
+
+typedef enum {
+ MRC_POST_CODE,
+ MRC_POST_CODE_WRITE,
+ MRC_POST_CODE_READ,
+ MRC_POST_CODE_MAX
+} MrcDebugPostCode;
+
+typedef struct {
+ UINT32 MrcData;
+ UINT32 Stream;
+ UINT32 Start;
+ UINT32 End;
+ UINT32 Current;
+ int Level;
+ UINT16 PostCode[MRC_POST_CODE_MAX];
+ UINT32 TopStackAddr; ///< Initial stack address.
+ UINT32 LowestStackAddr; ///< Track the lowest stack address used through MrcPrintfVaList()
+} MrcDebug;
+
+typedef UINT16 MrcPostCode;
+typedef UINT8 MrcClockRatio; ///< This value times the MrcRefClkSelect determines the MrcFrequency.
+typedef UINT32 MrcGfxDataSize; ///< The size of the stolen graphics data memory, in MBytes.
+typedef UINT32 MrcGfxGttSize; ///< The size of the graphics translation table, in MBytes.
+
+
+///
+/// This data structure contains all the "DDR power saving data" values that are considered output by the MRC.
+/// The following are memory controller level definitions. All channels on a controller are set to these values.
+///
+typedef struct {
+ BOOLEAN BaseFlag; ///< Indicates if the base line of power was already calculated.
+ UINT16 BaseSavingRd; ///< Indicates the base line of power consume by the ddr on read.
+ UINT16 BaseSavingWr; ///< Indicates the base line of power consume by the ddr on write.
+ UINT16 BaseSavingCmd; ///< Indicates the base line of power consume by the ddr on command.
+ UINT16 MrcSavingRd; ///< Indicates the power consume by the ddr on read at the end of MRC.
+ UINT16 MrcSavingWr; ///< Indicates the power consume by the ddr on write at the end of MRC.
+ UINT16 MrcSavingCmd; ///< Indicates the power consume by the ddr on command at the end of MRC.
+} MrcOdtPowerSaving;
+
+///
+/// The memory controller capabilities.
+///
+typedef union {
+ UINT32 Data;
+ UINT16 Data16[2];
+ UINT8 Data8[4];
+} MrcCapabilityIdA;
+
+typedef union {
+ UINT32 Data;
+ UINT16 Data16[2];
+ UINT8 Data8[4];
+} MrcCapabilityIdB;
+
+typedef union {
+ UINT64 Data;
+ struct {
+ MrcCapabilityIdA A;
+ MrcCapabilityIdB B;
+ } Data32;
+} MrcCapabilityId;
+
+///
+/// MRC version description.
+///
+typedef struct {
+ UINT8 Major; ///< Major version number
+ UINT8 Minor; ///< Minor version number
+ UINT8 Rev; ///< Revision number
+ UINT8 Build; ///< Build number
+} MrcVersion;
+
+///
+/// Memory map configuration information.
+///
+typedef struct {
+ UINT32 TomMinusMe;
+ UINT32 ToludBase;
+ UINT32 BdsmBase;
+ UINT32 GttBase;
+ UINT32 GraphicsControlRegister;
+ UINT32 TsegBase;
+ BOOLEAN ReclaimEnable;
+ UINT32 RemapBase;
+ UINT32 RemapLimit;
+ UINT32 TouudBase;
+ UINT32 TotalPhysicalMemorySize;
+ UINT32 MeStolenBase;
+ UINT32 MeStolenSize;
+ UINT32 GdxcMotBase;
+ UINT32 GdxcMotSize;
+ UINT32 GdxcIotBase;
+ UINT32 GdxcIotSize;
+ UINT32 DprSize;
+ UINT32 PttStolenBase;
+ UINT32 PrmrrBase;
+ UINT32 LowestBase;
+} MrcMemoryMap;
+
+///
+/// Real time clock information.
+///
+typedef struct {
+ UINT8 Seconds; ///< Seconds, 0-59
+ UINT8 Minutes; ///< Minutes, 0-59
+ UINT8 Hours; ///< Hours, 0-23
+ UINT8 DayOfMonth; ///< Day of the month, 1-31
+ UINT8 Month; ///< Month of the year, 1-12
+ UINT16 Year; ///< Year, 0-65535
+} MrcBaseTime;
+
+///
+/// DIMM timings
+///
+typedef struct {
+ UINT32 tCK; ///< Memory cycle time, in femtoseconds.
+ UINT16 NMode; ///< Number of tCK cycles for the channel DIMM's command rate mode.
+ UINT16 tCL; ///< Number of tCK cycles for the channel DIMM's CAS latency.
+ UINT16 tCWL; ///< Number of tCK cycles for the channel DIMM's minimum CAS write latency time.
+ UINT16 tFAW; ///< Number of tCK cycles for the channel DIMM's minimum four activate window delay time.
+ UINT16 tRAS; ///< Number of tCK cycles for the channel DIMM's minimum active to precharge delay time.
+ UINT16 tRCDtRP; ///< Number of tCK cycles for the channel DIMM's minimum RAS# to CAS# delay time and Row Precharge delay time.
+ UINT16 tREFI; ///< Number of tCK cycles for the channel DIMM's minimum Average Periodic Refresh Interval.
+ UINT16 tRFC; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRFC2; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRFC4; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRPab; ///< Number of tCK cycles for the channel DIMM's minimum row precharge delay time for all banks.
+ UINT16 tRRD; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time.
+ UINT16 tRRD_L; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for same bank groups.
+ UINT16 tRRD_S; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for different bank groups.
+ UINT16 tRTP; ///< Number of tCK cycles for the channel DIMM's minimum internal read to precharge command delay time.
+ UINT16 tWR; ///< Number of tCK cycles for the channel DIMM's minimum write recovery time.
+ UINT16 tWTR; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time.
+ UINT16 tWTR_L; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for same bank groups.
+ UINT16 tWTR_S; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for different bank groups.
+} MrcTiming;
+
+typedef struct {
+ INT32 Mtb; ///< Medium time base.
+ INT32 Ftb; ///< Fine time base.
+} MrcTimeBase;
+
+typedef struct {
+ UINT8 Left; ///< The left side of the timing eye.
+ UINT8 Center; ///< The center of the timing eye.
+ UINT8 Right; ///< The right side of the timing eye.
+} MrcDqTimeMargin;
+
+typedef struct {
+ UINT8 High; ///< The high side of the Vref eye.
+ UINT8 Center; ///< The center of the Vref eye.
+ UINT8 Low; ///< The low side of the Vref eye.
+} MrcDqVrefMargin;
+
+typedef struct {
+ UINT8 Left; ///< The left side of the command eye.
+ UINT8 Right; ///< The right side of the command eye.
+ UINT8 High; ///< The high side of the command eye.
+ UINT8 Low; ///< The low side of the command eye.
+} MrcCommandMargin;
+
+typedef struct {
+ UINT8 Left; ///< The left side of the receive enable eye.
+ UINT8 Right; ///< The right side of the receive enableeye.
+} MrcRecvEnMargin;
+
+typedef struct {
+ UINT8 Left; ///< The left side of the write leveling eye.
+ UINT8 Right; ///< The right side of the write leveling eye.
+} MrcWrLevelMargin;
+
+typedef struct {
+ UINT8 SpdValid[sizeof (MrcSpd) / (CHAR_BITS * sizeof (UINT8))]; ///< Each valid bit maps to SPD byte.
+ UINT8 MrcSpdString[3]; ///< The SPD data start marker. This must be located at the start of the SPD data structure. It includes this string plus the following flag.
+ union {
+ struct {
+ UINT8 DimmNumber : 4; ///< SPD zero based DIMM number.
+ UINT8 ChannelNumber : 3; ///< SPD zero based channel number.
+ UINT8 MdSocket : 1; ///< 0 = memory down, 1 = socketed.
+ } Bit;
+ UINT8 Data;
+ } Flag;
+ MrcSpd Data; ///< The SPD data for each DIMM. SPDGeneral field = 0 when absent.
+} MrcSpdData;
+
+typedef UINT8 (*MRC_IO_READ_8) (UINT32 IoAddress);
+typedef UINT16 (*MRC_IO_READ_16) (UINT32 IoAddress);
+typedef UINT32 (*MRC_IO_READ_32) (UINT32 IoAddress);
+typedef void (*MRC_IO_WRITE_8) (UINT32 IoAddress, UINT8 Value);
+typedef void (*MRC_IO_WRITE_16) (UINT32 IoAddress, UINT16 Value);
+typedef void (*MRC_IO_WRITE_32) (UINT32 IoAddress, UINT32 Value);
+typedef UINT8 (*MRC_MMIO_READ_8) (UINT32 Address);
+typedef UINT16 (*MRC_MMIO_READ_16) (UINT32 Address);
+typedef UINT32 (*MRC_MMIO_READ_32) (UINT32 Address);
+typedef UINT64 (*MRC_MMIO_READ_64) (UINT32 Address);
+typedef UINT8 (*MRC_MMIO_WRITE_8) (UINT32 Address, UINT8 Value);
+typedef UINT16 (*MRC_MMIO_WRITE_16) (UINT32 Address, UINT16 Value);
+typedef UINT32 (*MRC_MMIO_WRITE_32) (UINT32 Address, UINT32 Value);
+typedef UINT64 (*MRC_MMIO_WRITE_64) (UINT32 Address, UINT64 Value);
+typedef UINT8 (*MRC_SMBUS_READ_8) (UINT32 Address, UINT32 *Status);
+typedef UINT16 (*MRC_SMBUS_READ_16) (UINT32 Address, UINT32 *Status);
+typedef UINT8 (*MRC_SMBUS_WRITE_8) (UINT32 Address, UINT8 Value, UINT32 *Status);
+typedef UINT16 (*MRC_SMBUS_WRITE_16) (UINT32 Address, UINT16 Value, UINT32 *Status);
+typedef UINT32 (*MRC_GET_PCI_DEVICE_ADDRESS) (UINT8 Bus, UINT8 Device, UINT8 Function, UINT8 Offset);
+typedef UINT32 (*MRC_GET_PCIE_DEVICE_ADDRESS) (UINT8 Bus, UINT8 Device, UINT8 Function, UINT8 Offset);
+typedef void (*MRC_GET_RTC_TIME) (UINT8 *Second, UINT8 *Minute, UINT8 *Hour, UINT8 *Day, UINT8 *Month, UINT16 *Year);
+typedef UINT64 (*MRC_GET_CPU_TIME) (void *MrcData);
+typedef void * (*MRC_MEMORY_COPY) (UINT8 *Destination, UINT8 *Source, UINT32 NumBytes);
+typedef void * (*MRC_MEMORY_SET_BYTE) (UINT8 *Destination, UINT32 NumBytes, UINT8 Value);
+typedef void * (*MRC_MEMORY_SET_WORD) (UINT16 *Destination, UINT32 NumWords, UINT16 Value);
+typedef void * (*MRC_MEMORY_SET_DWORD) (UINT32 *Destination, UINT32 NumDwords, UINT32 Value);
+typedef UINT64 (*MRC_LEFT_SHIFT_64) (UINT64 Data, UINT32 NumBits);
+typedef UINT64 (*MRC_RIGHT_SHIFT_64) (UINT64 Data, UINT32 NumBits);
+typedef UINT64 (*MRC_MULT_U64_U32) (UINT64 Multiplicand, UINT32 Multiplier);
+typedef UINT64 (*MRC_DIV_U64_U64) (UINT64 Dividend, UINT64 Divisor, UINT64 *Remainder);
+typedef BOOLEAN (*MRC_GET_SPD_DATA) (UINT8 BootMode, UINT8 SpdAddress, UINT8 *SpdData, UINT8 *Ddr3Table, UINT32 Ddr3TableSize, UINT8 *Ddr4Table, UINT32 Ddr4TableSize, UINT8 *LpddrTable, UINT32 LpddrTableSize);
+typedef BOOLEAN (*MRC_GET_RANDOM_NUMBER) (UINT32 *Rand);
+typedef UINT32 (*MRC_CPU_MAILBOX_READ) (UINT32 Type, UINT32 Command, UINT32 *Value, UINT32 *Status);
+typedef UINT32 (*MRC_CPU_MAILBOX_WRITE) (UINT32 Type, UINT32 Command, UINT32 Value, UINT32 *Status);
+typedef UINT32 (*MRC_GET_MEMORY_VDD) (void *MrcData, UINT32 DefaultVdd);
+typedef UINT32 (*MRC_SET_MEMORY_VDD) (void *MrcData, UINT32 DefaultVdd, UINT32 Value);
+typedef UINT32 (*MRC_CHECKPOINT) (void *MrcData, UINT32 CheckPoint, void *Scratch);
+typedef void (*MRC_DEBUG_HOOK) (void *GlobalData, UINT16 DisplayDebugNumber);
+typedef void (*MRC_PRINT_STRING) (void *String);
+typedef UINT8 (*MRC_GET_RTC_CMOS) (UINT8 Location);
+typedef UINT64 (*MRC_MSR_READ_64) (UINT32 Location);
+typedef UINT64 (*MRC_MSR_WRITE_64) (UINT32 Location, UINT64 Data);
+typedef void (*MRC_RETURN_FROM_SMC) (void *GlobalData, UINT32 MrcStatus);
+typedef void (*MRC_DRAM_RESET) (UINT32 PciEBaseAddress, UINT32 ResetValue);
+typedef void (*MRC_SET_LOCK_PRMRR) (UINT32 PrmrrBase, UINT32 PrmrrSize);
+typedef void (*MRC_TXT_ACHECK) (void);
+
+///
+/// Function calls that are called external to the MRC.
+/// This structure needs to be aligned with SA_FUNCTION_CALLS. All functions that are
+/// not apart of SA_FUNCTION_CALLS need to be at the end of the structure.
+///
+typedef struct {
+ MRC_IO_READ_8 MrcIoRead8;
+ MRC_IO_READ_16 MrcIoRead16;
+ MRC_IO_READ_32 MrcIoRead32;
+ MRC_IO_WRITE_8 MrcIoWrite8;
+ MRC_IO_WRITE_16 MrcIoWrite16;
+ MRC_IO_WRITE_32 MrcIoWrite32;
+ MRC_MMIO_READ_8 MrcMmioRead8;
+ MRC_MMIO_READ_16 MrcMmioRead16;
+ MRC_MMIO_READ_32 MrcMmioRead32;
+ MRC_MMIO_READ_64 MrcMmioRead64;
+ MRC_MMIO_WRITE_8 MrcMmioWrite8;
+ MRC_MMIO_WRITE_16 MrcMmioWrite16;
+ MRC_MMIO_WRITE_32 MrcMmioWrite32;
+ MRC_MMIO_WRITE_64 MrcMmioWrite64;
+ MRC_SMBUS_READ_8 MrcSmbusRead8;
+ MRC_SMBUS_READ_16 MrcSmbusRead16;
+ MRC_SMBUS_WRITE_8 MrcSmbusWrite8;
+ MRC_SMBUS_WRITE_16 MrcSmbusWrite16;
+ MRC_GET_PCI_DEVICE_ADDRESS MrcGetPciDeviceAddress;
+ MRC_GET_PCIE_DEVICE_ADDRESS MrcGetPcieDeviceAddress;
+ MRC_GET_RTC_TIME MrcGetRtcTime;
+ MRC_GET_CPU_TIME MrcGetCpuTime;
+ MRC_MEMORY_COPY MrcCopyMem;
+ MRC_MEMORY_SET_BYTE MrcSetMem;
+ MRC_MEMORY_SET_WORD MrcSetMemWord;
+ MRC_MEMORY_SET_DWORD MrcSetMemDword;
+ MRC_LEFT_SHIFT_64 MrcLeftShift64;
+ MRC_RIGHT_SHIFT_64 MrcRightShift64;
+ MRC_MULT_U64_U32 MrcMultU64x32;
+ MRC_DIV_U64_U64 MrcDivU64x64;
+ MRC_GET_SPD_DATA MrcGetSpdData;
+ MRC_GET_RANDOM_NUMBER MrcGetRandomNumber;
+ MRC_CPU_MAILBOX_READ MrcCpuMailboxRead;
+ MRC_CPU_MAILBOX_WRITE MrcCpuMailboxWrite;
+ MRC_GET_MEMORY_VDD MrcGetMemoryVdd;
+ MRC_SET_MEMORY_VDD MrcSetMemoryVdd;
+ MRC_CHECKPOINT MrcCheckpoint;
+ MRC_DEBUG_HOOK MrcDebugHook;
+ MRC_PRINT_STRING MrcPrintString;
+ MRC_GET_RTC_CMOS MrcRtcCmos;
+ MRC_MSR_READ_64 MrcReadMsr64;
+ MRC_MSR_WRITE_64 MrcWriteMsr64;
+ MRC_RETURN_FROM_SMC MrcReturnFromSmc;
+ MRC_DRAM_RESET MrcDramReset;
+ MRC_SET_LOCK_PRMRR MrcSetLockPrmrr;
+ MRC_TXT_ACHECK MrcTxtAcheck;
+} MRC_FUNCTION;
+
+///
+///*****************************************
+/// Output related "global data" structures.
+///*****************************************
+///
+/// This data structure contains all the "global data" values that are considered output by the MRC.
+/// The following are SDRAM level definitions. All ranks on a rank are set to these values.
+///
+/* Commented out until needed, in order to save space.
+typedef struct {
+} MrcSdramOut;
+*/
+
+///
+/// This data structure contains all the "global data" values that are considered output by the MRC.
+/// The following are rank level definitions. All ranks on a DIMM are set to these values.
+///
+typedef struct {
+//MrcSdramOut Sdram[MAX_SDRAM_IN_DIMM]; ///< The following are SDRAM level definitions.
+ UINT16 MR[MAX_MR_IN_DIMM]; ///< DRAM mode register value.
+ UINT16 MR11; ///< LPDDR3 ODT MR
+ UINT8 Ddr4PdaMr6[MAX_SDRAM_IN_DIMM]; ///< DDR4 MR6[6:0] for per-DRAM VrefDQ (PDA)
+#if (SUPPORT_DDR4 == SUPPORT)
+ UINT8 Device[MAX_SDRAM_IN_DIMM]; ///< Which Bytes are tied to which Device where BIT0 set means Byte 0
+#endif //SUPPORT_DDR4
+} MrcRankOut;
+
+///
+/// This data structure contains all the "global data" values that are considered output by the MRC.
+/// The following are DIMM level definitions. All ranks on a DIMM are set to these values.
+///
+typedef struct {
+ MrcDimmSts Status; ///< See MrcDimmSts for the definition of this field.
+ MrcTiming Timing[MAX_PROFILE]; ///< The DIMMs timing values.
+ MrcVddSelect VddVoltage[MAX_PROFILE]; ///< The voltage (VDD) setting for this DIMM, per profile.
+ BOOLEAN EccSupport; ///< TRUE if ECC is enabled and supported on this DIMM.
+ BOOLEAN IgnoreNonEccDimm; ///< TRUE if a DIMM without ECC capability should be ignored.
+ BOOLEAN AddressMirrored; ///< TRUE if the DIMM is address mirrored.
+ BOOLEAN SelfRefreshTemp; ///< TRUE if the DIMM supports self refresh extended operating temperature range (SRT).
+ BOOLEAN AutoSelfRefresh; ///< TRUE if the DIMM supports automatic self refresh (ASR).
+ BOOLEAN PartialSelfRefresh; ///< TRUE if the DIMM supports Partial Array Self Refresh (PASR).
+ BOOLEAN OnDieThermalSensor; ///< TRUE if the DIMM supports On-die Thermal Sensor (ODTS) Readout.
+ BOOLEAN ExtendedTemperRange; ///< TRUE if the DIMM supports Extended Temperature Range (ETR).
+ BOOLEAN ExtendedTemperRefresh; ///< TRUE if the DIMM supports 1x Extended Temperature Refresh rate, FALSE = 2x.
+ MrcDdrType DdrType; ///< DDR type: DDR3 or LPDDR3
+ MEMORY_PACKAGE ModuleType; ///< Module type: UDIMM, SO-DIMM, etc.
+ UINT32 SdramCount; ///< The number of SDRAM components on a DIMM.
+ UINT32 DimmCapacity; ///< DIMM size in MBytes.
+ UINT32 RowSize; ///< The DIMMs row address size.
+ UINT16 ColumnSize; ///< The DIMMs column address size.
+ UINT16 Crc; ///< Calculated CRC16 of the DIMM's provided SPD. Can be used to detect DIMM change.
+ UINT8 RankInDimm; ///< The number of ranks in this DIMM.
+ UINT8 Banks; ///< Number of banks the DIMM contains.
+ UINT8 BankGroups; ///< Number of bank groups the DIMM contains.
+ UINT8 PrimaryBusWidth; ///< DIMM primary bus width.
+ UINT8 SdramWidth; ///< DIMM SDRAM width.
+ UINT8 SdramWidthIndex; ///< DIMM SDRAM width index (0 = x4, 1 = x8, 2 = x16, 3 = x32).
+ UINT8 DensityIndex; ///< Total SDRAM capacity index (0 = 256Mb, 1 = 512Mb, 2 = 1Gb, etc).
+ UINT8 tMAC; ///< Maximum Activate Count for pTRR.
+ UINT8 ReferenceRawCard; ///< Indicates which JEDEC reference design raw card was used as the basis for the module assembly.
+ UINT8 ReferenceRawCardRevision; ///< Indicates which JEDEC reference design raw card revsion.
+ UINT8 XmpSupport; ///< Indicates if XMP profiles are supported. 0 = None, 1 = XMP1 only, 2 = XMP2 only, 3 = All.
+ UINT8 XmpRevision; ///< Indicates the XMP revision of this DIMM. 0 = None, 12h = 1.2, 13h = 1.3.
+ MrcRankOut Rank[MAX_RANK_IN_DIMM]; ///< The following are rank level definitions.
+} MrcDimmOut;
+
+///
+/// This data structure contains all the "global data" values that are considered output by the MRC.
+/// The following are channel level definitions. All DIMMs on a memory channel are set to these values.
+///
+typedef struct {
+ MrcChannelSts Status; ///< Indicates whether this channel should be used.
+ MrcVirtualChannel VirtualChannel; ///< define the virtual channel type A or B.
+ MrcTiming Timing[MAX_PROFILE]; ///< The channel timing values.
+ MrcTimeBase TimeBase[MAX_DIMMS_IN_CHANNEL][MAX_PROFILE]; ///< Medium and fine timebases for each DIMM in the channel and each memory profile.
+ UINT32 Capacity; ///< Amount of memory in this channel, in MBytes.
+ UINT32 DimmCount; ///< Number of valid DIMMs that exist in the channel.
+ UINT32 DataOffsetTrain[MAX_SDRAM_IN_DIMM]; ///< DataOffsetTrain CR
+ UINT32 DataCompOffset[MAX_SDRAM_IN_DIMM]; ///< DataCompOffset CR
+ UINT32 CkeCmdPiCode[MAX_COMMAND_GROUPS]; ///< CKE CmdPiCode CR, per group
+ UINT32 CmdsCmdPiCode[MAX_COMMAND_GROUPS]; ///< CmdS CmdPiCode CR, per group
+ UINT32 CmdnCmdPiCode[MAX_COMMAND_GROUPS]; ///< CmdN CmdPiCode CR, per group
+ UINT16 TxDqs[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< TxDQS PI Code
+ UINT16 TxDq[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< TxDQ Pi Code
+ UINT16 RcvEn[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< RcvEn PI Code
+ UINT16 WlDelay[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< WlDelay PI Code
+ UINT8 ClkPiCode[MAX_RANK_IN_CHANNEL]; ///< Clk Pi Code
+ UINT8 CtlPiCode[MAX_RANK_IN_CHANNEL]; ///< Ctl Pi Code
+ UINT8 CkePiCode[MAX_RANK_IN_CHANNEL]; ///< Ctl Pi Code
+ UINT8 TxEq[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< TxEq setting
+ MrcCommandMargin Command[MAX_RANK_IN_CHANNEL]; ///< Cmd setting
+ MrcDqTimeMargin RxDqPb[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM][MAX_BITS]; ///< Rx PerBit Pi Code
+ MrcDqTimeMargin TxDqPb[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM][MAX_BITS]; ///< Tx PerBit Pi Code
+ MrcDqVrefMargin RxDqVrefPb[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM][MAX_BITS]; ///< Rx PerBit Vref
+ MrcDqVrefMargin TxDqVrefPb[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM][MAX_BITS]; ///< Rx PerBit Vref
+ MrcRecvEnMargin ReceiveEnable[MAX_RANK_IN_CHANNEL]; ///< Receive enable per rank
+ MrcWrLevelMargin WriteLevel[MAX_RANK_IN_CHANNEL]; ///< Write leveling per rank
+ UINT8 IoLatency[MAX_RANK_IN_CHANNEL]; ///< IOLatency
+ UINT8 RTLatency[MAX_RANK_IN_CHANNEL]; ///< RoundTripLatency
+ UINT32 RTIoComp; ///< RoundTrip IO Compensation of the Channel
+ UINT8 RxVref[MAX_SDRAM_IN_DIMM]; ///< RX Vref in steps of 7.9 mv
+ UINT8 RxEq[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< RxEQ Setting
+ UINT8 RxDqsP[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< RxDQSP PI Code
+ UINT8 RxDqsN[MAX_RANK_IN_CHANNEL][MAX_SDRAM_IN_DIMM]; ///< RxDQSN PI Code
+ UINT8 ValidRankBitMask; ///< Bit map of the populated ranks per channel
+ UINT8 ValidCkeBitMask; ///< Bit map of the used CKE pins per channel
+ MrcDimmOut Dimm[MAX_DIMMS_IN_CHANNEL]; ///< DIMM specific output variables.
+} MrcChannelOut;
+
+///
+/// This data structure contains all the "global data" values that are considered output by the MRC.
+/// The following are memory controller level definitions. All channels on a controller are set to these values.
+///
+typedef struct {
+ MrcControllerSts Status; ///< Indicates whether this controller should be used.
+ UINT16 DeviceId; ///< The PCI device id of this memory controller.
+ UINT8 RevisionId; ///< The PCI revision id of this memory controller.
+ UINT8 ChannelCount; ///< Number of valid channels that exist on the controller.
+ MrcChannelOut Channel[MAX_CHANNEL]; ///< The following are channel level definitions.
+} MrcControllerOut;
+
+///
+///********************************************
+/// Saved data related "global data" structures.
+///********************************************
+///
+
+///
+/// This data structure contains all the "global data" values that are considered to be needed
+/// by the MRC between power state transitions (S0->S3->S0) and also fast and warm boot modes.
+/// The following are DIMM level definitions.
+///
+typedef struct {
+ UINT8 SpdDramDeviceType; ///< Save SPD DramDeviceType information needed for SMBIOS structure creation.
+ UINT8 SpdModuleType; ///< Save SPD ModuleType information needed for SMBIOS structure creation.
+ UINT8 SpdModuleMemoryBusWidth; ///< Save SPD ModuleMemoryBusWidth information needed for SMBIOS structure creation.
+ UINT8 SpdSave[MAX_SPD_SAVE]; ///< Save SPD Manufacturing information needed for SMBIOS structure creation.
+} MrcDimmSave;
+
+///
+/// This data structure contains all the "global data" values that are considered to be needed
+/// by the MRC between power state transitions (S0->S3->S0) and also fast and warm boot modes.
+/// The following are channel level definitions.
+///
+typedef struct {
+ MrcChannelSts Status; ///< Indicates whether this channel should be used.
+ UINT32 DimmCount; ///< Number of valid DIMMs that exist in the channel.
+ UINT8 ValidRankBitMask; ///< Bit map of the populated ranks per channel
+ MrcTiming Timing[MAX_PROFILE]; ///< The channel timing values.
+ MrcDimmOut Dimm[MAX_DIMMS_IN_CHANNEL]; ///< Save the DIMM output characteristics.
+ MrcDimmSave DimmSave[MAX_DIMMS_IN_CHANNEL]; ///< Save SPD information needed for SMBIOS structure creation.
+} MrcChannelSave;
+
+///
+/// This data structure contains all the "global data" values that are considered to be needed
+/// by the MRC between power state transitions (S0->S3->S0) and also fast and warm boot modes.
+/// The following are controller level definitions.
+///
+typedef struct {
+ MrcControllerSts Status; ///< Indicates whether this controller should be used.
+ UINT8 ChannelCount; ///< Number of valid channels that exist on the controller.
+ MrcChannelSave Channel[MAX_CHANNEL]; ///< The following are channel level definitions.
+} MrcContSave;
+
+///
+/// This data structure contains all the "global data" values that are considered to be needed
+/// by the MRC between power state transitions (S0->S3->S0) and also fast and warm boot modes.
+/// The following are system level definitions.
+///
+typedef struct {
+ UINT32 Crc; ///< The CRC-32 of the data in this structure.
+} MrcSaveHeader;
+
+//
+// ------- IMPORTANT NOTE --------
+// MRC_MC_REGISTER_COUNT in MrcInterface.h should match the table in MrcSaveRestore.c.
+// Update this define whenever you add/remove registers from this table.
+//
+#define MRC_REGISTER_COUNT_COMMON (1376 / sizeof (UINT32)) ///< The number of MC registers that need to be saved (common)
+#define MRC_REGISTER_COUNT_SAGV (1528 / sizeof (UINT32)) ///< The number of MC registers that need to be saved (per SA GV point)
+
+typedef struct {
+ MrcCapabilityId McCapId; ///< The memory controller's capabilities.
+ UINT32 RegSaveCommon[MRC_REGISTER_COUNT_COMMON]; ///< The MC registers that are common to both SA GV points
+ UINT32 RegSaveLow[MRC_REGISTER_COUNT_SAGV]; ///< The MC registers for the Low SA GV point
+ UINT32 RegSaveHigh[MRC_REGISTER_COUNT_SAGV]; ///< The MC registers for the High SA GV point, or for SA GV Disabled case
+ UINT32 MeStolenSize; ///< The managebility engine memory size, in Mbyte units.
+ MrcCpuStepping CpuStepping; ///< The last cold boot happended with this CPU stepping.
+ MrcCpuModel CpuModel; ///< The last cold boot happended with this CPU model.
+ MrcCpuFamily CpuFamily; ///< CPU is Skylake or Kabylake
+ MrcVersion Version; ///< The last cold boot happended with this MRC version.
+ UINT32 SaMemCfgCrc; ///< The CRC32 of the system agent memory configuration structure.
+ MrcContSave Controller[MAX_CONTROLLERS]; ///< The following are controller level definitions.
+ MrcFrequency Frequency; ///< The system's common memory controller frequency.
+ UINT32 MemoryClock; ///< The system's common memory controller clock, in femtoseconds.
+ BOOLEAN OddRatioModeLow; ///< If Odd Ratio Mode is enabled, QCLK frequency has an addition of 133/100 MHz. This is for SAGV Low point.
+ BOOLEAN OddRatioModeHigh; ///< If Odd Ratio Mode is enabled, QCLK frequency has an addition of 133/100 MHz. This is for SAGV High point, or SAGV disabled / fixed high / fixed low
+ MrcRefClkSelect RefClk; ///< The memory controller is going to use this reference clock.
+ MrcClockRatio Ratio; ///< Request for this memory controller to use this clock ratio.
+ MrcVddSelect VddVoltage[MAX_PROFILE]; ///< The voltage (VDD) setting for all DIMMs in the system, per profile.
+ BOOLEAN EccSupport; ///< TRUE if ECC is enabled and supported on this controller.
+ MrcDdrType DdrType; ///< DDR type: DDR3, DDR4, or LPDDR3
+ UINT32 DefaultXmptCK[MAX_PROFILE - XMP_PROFILE1]; ///< The Default XMP tCK values read from SPD.
+ UINT8 XmpProfileEnable; ///< If XMP capable DIMMs are detected, this will indicate which XMP Profiles are common among all DIMMs.
+ BOOLEAN BinnedLpddrDevices; ///< Binned LPDDR3 devices (6Gb/12Gb/etc)
+ BOOLEAN TCRSensitiveHynixDDR4; ///< TCR sensitive Hynix DDR4 in the system
+ BOOLEAN TCRSensitiveMicronDDR4; ///< TCR sensitive Micron DDR4 in the system
+ BOOLEAN LpddrEctDone; ///< Set to TRUE once Early Command Training on LPDDR is done, and we can run JEDEC Init
+ UINT8 BerEnable; ///< BER Enable (and # of Addresses)
+ UINT64 BerAddress[4]; ///< BER Addresses
+} MrcSaveData;
+
+typedef struct {
+ UINT32 Size; ///< The size of this structure, in bytes. Must be the first entry in this structure.
+ MrcDebug Debug; ///< MRC debug related variables used for serial output and debugging purposes.
+ MrcVersion Version; ///< The memory reference code version.
+ MrcFrequency FreqMax; ///< The requested maximum valid frequency.
+ MrcFrequency Frequency; ///< The system's common memory controller frequency.
+ UINT32 MemoryClockMax; ///< The system's common memory controller maximum clock, in femtoseconds.
+ UINT32 MemoryClock; ///< The system's common memory controller clock, in femtoseconds.
+ MrcRefClkSelect RefClk; ///< The memory controller is going to use this reference clock.
+ MrcClockRatio Ratio; ///< Request for this memory controller to use this clock ratio.
+ MrcMemoryMap MemoryMapData; ///< The system's memory map data.
+ MrcGfxDataSize GraphicsStolenSize; ///< Graphics Data Stolen Memory size in MB
+ MrcGfxGttSize GraphicsGttSize; ///< GTT graphics stolen memory size in MB
+ MrcVddSelect VddVoltage[MAX_PROFILE]; ///< The currently running voltage (VDD) setting for all DIMMs in the system, per profile.
+ MrcGdxc Gdxc; ///< GDXC enable and size.
+ BOOLEAN VddVoltageDone; ///< To determine if VddVoltageDone update has been done already
+ BOOLEAN EccSupport; ///< TRUE if ECC is enabled and supported on this controller.
+ BOOLEAN EnDumRd; ///< Enable/Disable Logic Analyzer
+ BOOLEAN RestoreMRs; ///< Enable/Disable restoring
+ BOOLEAN LpddrEctDone; ///< Set to TRUE once Early Command Training on LPDDR is done, and we can run JEDEC Init
+ BOOLEAN LpddrWLUpdated; ///< Set to TRUE once LPDDR WL Memory Set has been updated
+ BOOLEAN JedecInitDone; ///< Set to TRUE once JEDEC Init on LPDDR/DDR4 is done
+ UINT32 DefaultXmptCK[MAX_PROFILE - XMP_PROFILE1]; ///< The Default XMP tCK values read from SPD.
+ UINT8 XmpProfileEnable; ///< If XMP capable DIMMs are detected, this will indicate which XMP Profiles are common among all DIMMs.
+ BOOLEAN Capable100; ///< The MC is capable of 100 reference clock (0 = no, 1 = yes).
+ BOOLEAN AutoSelfRefresh; ///< Indicates ASR is supported for all the DIMMS for 2xRefresh
+ MrcDdrType DdrType; ///< Current memory type: DDR3, DDR4, or LPDDR3
+ MrcSpdStatus SpdSecurityStatus; ///< Status variable to inform BIOS that memory contains an alias.
+ UINT32 MrcTotalChannelLimit; ///< The maximum allowed memory size per channel, in MBytes.
+ UINT8 SdramCount; ///< The number of SDRAM components on a DIMM.
+ UINT16 Qclkps; ///< Qclk period in pS
+ UINT8 DQPat; ///< Global Variables storing the current DQPat REUT Test
+ INT8 DQPatLC; ///< Global Variables storing the current DQPat Loopcount
+ UINT8 ValidRankMask; ///< Rank bit map - includes both channels
+ UINT8 ValidChBitMask; ///< Channel bit map of the populated channels
+ BOOLEAN UpmPwrRetrainFlag; ///< A flag that indicates if training with higher UPM/PWR limits.
+ UINT32 MarginResult[MAX_RESULT_TYPE][MAX_RANK_IN_CHANNEL][MAX_CHANNEL][MAX_SDRAM_IN_DIMM][MAX_EDGES]; ///< Stores last margin measurement.
+ BOOLEAN MarginSignReversed[MAX_RANK_IN_CHANNEL][MAX_CHANNEL][MAX_SDRAM_IN_DIMM][MAX_EDGES]; ///< Indicates if the Margin Sign is Reversed
+ MrcOdtPowerSaving OdtPowerSavingData; ///< ODT power savings data.
+ BOOLEAN TxDIMMVref[MAX_CHANNEL]; ///< Whether Write DIMM Vref is enabled based on Channel
+ UINT32 MchBarWriteCount; ///< The number of MMIO writes performed during MRC execution.
+ UINT32 MchBarReadCount; ///< The number of MMIO reads performed during MRC execution.
+ UINT8 BerEnable; ///< BER Enable (and # of Addresses)
+ UINT64 BerAddress[4]; ///< BER Addresses
+ UINT8 CmdVLoop; ///< Keeps track of the # of CmdV training step runned
+ UINT8 CmdVLoopStatus; ///< Keeps the last status of the CmdV training step
+ UINT8 tMAC; ///< Maximum Activate Count for pTRR.
+ UINT8 LpddrMemWriteLatencySet; ///< 0 = Set A (WL), 1 = Set B (WL) if supported
+ BOOLEAN Ddr4PdaEnable; ///< Current status of PDA - if true all the Mr6 operations need to use PDA mode.
+ BOOLEAN BinnedLpddrDevices; ///< Binned LPDDR3 devices (6Gb/12Gb/etc)
+ MrcControllerOut Controller[MAX_CONTROLLERS]; ///< The following are controller level definitions.
+ BOOLEAN TCRSensitiveHynixDDR4; ///< TCR sensitive Hynix DDR4 in the system
+ BOOLEAN TCRSensitiveMicronDDR4; ///< TCR sensitive Micron DDR4 in the system
+ BOOLEAN OddRatioMode; ///< If Odd Ratio Mode is enabled, QCLK frequency has an addition of 133/100 MHz
+ BOOLEAN LpddrDramOdt; ///< Indicates if LPDDR DRAM ODT is used - Only used for 2133+
+#ifdef BDAT_SUPPORT
+ union {
+ MRC_BDAT_SCHEMA_LIST_HOB *Pointer; ///< Pointer to the BDAT schema list.
+ UINT64 Data;
+ } BdatSchemasHob;
+ union {
+ BDAT_MEMORY_DATA_HOB *Pointer; ///< Pointer to the BDAT memory data HOB.
+ UINT64 Data;
+ } BdatMemoryHob[MAX_SCHEMA_LIST_LENGTH];
+#endif
+
+} MrcOutput;
+
+///
+///****************************************
+/// Input related "global data" structures.
+///****************************************
+///
+/// This data structure contains all the "global data" values that are considered input by the MRC.
+/// The following are SDRAM level definitions. All ranks on a rank are set to these values.
+///
+/* Commented out until needed, in order to save space.
+typedef struct {
+ UINT8 Placeholder; ///< TODO: Is there anything that needs to go in here?
+} MrcSdramIn;
+*/
+
+///
+/// This data structure contains all the "global data" values that are considered input by the MRC.
+/// The following are rank level definitions. All ranks on a DIMM are set to these values.
+///
+/* Commented out until needed, in order to save space.
+typedef struct {
+ MrcSdramIn Sdram[MAX_SDRAM_IN_DIMM]; ///< The following are SDRAM level definitions.
+} MrcRankIn;
+*/
+
+///
+/// This data structure contains all the "global data" values that are considered input by the MRC.
+/// The following are DIMM level definitions. All ranks on a DIMM are set to these values.
+///
+typedef struct {
+ MrcDimmSts Status; ///< Indicates whether this DIMM should be used.
+ MrcSpdData Spd; ///< The SPD data for each DIMM. SPDGeneral field = 0 when absent.
+ MrcTiming Timing; ///< The DIMMs requested timing overrides.
+ UINT8 SpdAddress; ///< The SMBus address for the DIMM's SPD data.
+//MrcRankIn Rank[MAX_RANK_IN_DIMM]; ///< The following are rank level definitions.
+} MrcDimmIn;
+
+///
+/// This data structure contains all the "global data" values that are considered input by the MRC.
+/// The following are channel level definitions. All DIMMs on a memory channel are set to these values.
+///
+typedef struct {
+ MrcChannelSts Status; ///< Indicates whether this channel should be used.
+ UINT32 DimmCount; ///< The maximum number of DIMMs on this channel.
+ MrcDimmIn Dimm[MAX_DIMMS_IN_CHANNEL]; ///< The following are DIMM level definitions.
+ UINT8 DqsMapCpu2Dram[8]; ///< Mapping from CPU DQS pins to SDRAM DQS pins
+ UINT8 DqMapCpu2Dram[8][MAX_BITS]; ///< Mapping from CPU DQ pins to SDRAM DQ pins
+ UINT8 DQByteMap[MrcIterationMax][2]; ///< Maps which PI clocks are used by what LPDDR DQ Bytes (from CPU side), per group
+ ///< DQByteMap[0] - ClkDQByteMap:
+ ///< If clock is per rank, program to [0xFF, 0xFF]
+ ///< If clock is shared by 2 ranks, program to [0xFF, 0] or [0, 0xFF]
+ ///< If clock is shared by 2 ranks but does not go to all bytes,
+ ///< Entry[i] defines which DQ bytes Group i services
+ ///< DQByteMap[1] - CmdNDQByteMap: Entry[0] is CmdN/CAA and Entry[1] is CmdN/CAB
+ ///< DQByteMap[2] - CmdSDQByteMap: Entry[0] is CmdS/CAA and Entry[1] is CmdS/CAB
+ ///< DQByteMap[3] - CkeDQByteMap : Entry[0] is CKE /CAA and Entry[1] is CKE /CAB
+ ///< For DDR, DQByteMap[3:1] = [0xFF, 0]
+ ///< DQByteMap[4] - CtlDQByteMap : Always program to [0xFF, 0] since we have 1 CTL / rank
+ ///< Variable only exists to make the code easier to use
+ ///< DQByteMap[5] - CmdVDQByteMap: Always program to [0xFF, 0] since we have 1 CA Vref
+ ///< Variable only exists to make the code easier to use
+} MrcChannelIn;
+
+///
+/// This data structure contains all the "global data" values that are considered input by the MRC.
+/// The following are memory controller level definitions. All channels on a controller are set to these values.
+///
+typedef struct {
+ MrcControllerSts Status; ///< Indicates whether this controller should be used.
+ UINT8 ChannelCount; ///< Number of valid channels that are requested on the controller.
+ MrcChannelIn Channel[MAX_CHANNEL]; ///< The following are channel level definitions.
+} MrcControllerIn;
+
+///
+/// This data structure contains all the "global data" values that are considered input by the MRC.
+/// The following are system level definitions. All memory controllers in the system are set to these values.
+///
+typedef struct {
+ //
+ // Start of synchronization to the SA MEMORY_CONFIGURATION structure.
+ // Alignment of this block must be maintained and field offsets must match.
+ //
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ UINT8 HobBufferSize; ///< Offset 28 Size of HOB buffer
+ //
+ // The following parameters are used only when SpdProfileSelected is UserDefined (CUSTOM PROFILE)
+ //
+ UINT8 MemoryProfile; ///< Offset 29 SPD XMP profile selection - for XMP supported DIMM: <b>0=Default DIMM profile</b>, 1=Customized profile, 2=XMP profile 1, 3=XMP profile 2.
+ UINT16 tCL; ///< Offset 30 User defined Memory Timing tCL value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 31=Maximum.
+ UINT16 tRCDtRP; ///< Offset 32 User defined Memory Timing tRCD value (same as tRP), valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 63=Maximum.
+ UINT16 tRAS; ///< Offset 34 User defined Memory Timing tRAS value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 64=Maximum.
+ UINT16 tWR; ///< Offset 36 User defined Memory Timing tWR value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, legal values: 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24.
+ UINT16 tRFC; ///< Offset 38 User defined Memory Timing tRFC value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 1023=Maximum.
+ UINT16 tRRD; ///< Offset 40 User defined Memory Timing tRRD value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 15=Maximum.
+ UINT16 tWTR; ///< Offset 42 User defined Memory Timing tWTR value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 28=Maximum.
+ UINT16 tRTP; ///< Offset 44 User defined Memory Timing tRTP value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 15=Maximum. DDR4 legal values: 5, 6, 7, 8, 9, 10, 12
+ UINT16 tFAW; ///< Offset 46 User defined Memory Timing tFAW value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 63=Maximum.
+ UINT16 tCWL; ///< Offset 48 User defined Memory Timing tCWL value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 20=Maximum.
+ UINT16 tREFI; ///< Offset 50 User defined Memory Timing tREFI value, valid when SpdProfileSelected is CUSTOM_PROFILE: <b>0=AUTO</b>, 65535=Maximum.
+ UINT16 VddVoltage; ///< Offset 52 DRAM voltage (Vdd) in millivolts: <b>0=Platform Default (no override)</b>, 1200=1.2V, 1350=1.35V etc.
+ UINT8 NModeSupport; ///< Offset 54 Memory N Mode Support - Enable user to select Auto, 1N or 2N: <b>0=AUTO</b>, 1=1N, 2=2N.
+
+ UINT8 McLock; ///< Offset 55 Enable/Disable memory configuration register locking: 0=Disable, <b>1=Enable</b>.
+ //
+ // Thermal Management
+ //
+ UINT32 ThermalManagement:1; ///< Offset 56 Memory Thermal Management Support: <b>0=Disable</b>, 1=Enable.
+ UINT32 PeciInjectedTemp:1; ///< - Enable/Disable memory temperatures to be injected to the processor via PECI: <b>0=Disable</b>, 1=Enable.
+ UINT32 ExttsViaTsOnBoard:1; ///< - Enable/Disable routing TS-on-Board's ALERT# and THERM# to EXTTS# pins on the PCH: <b>0=Disable</b>, 1=Enable.
+ UINT32 ExttsViaTsOnDimm:1; ///< - Enable/Disable routing TS-on-DIMM's ALERT# to EXTTS# pin on the PCH: <b>0=Disable</b>, 1=Enable.
+ UINT32 VirtualTempSensor:1; ///< - Enable/Disable Virtual Temperature Sensor (VTS): <b>0=Disable</b>, 1=Enable.
+ UINT32 RsvdBits0:27;
+ //
+ // Training Algorithms
+ //
+ TrainingStepsEn TrainingEnables; ///< Offset 60 Options to Enable individual training steps
+
+ UINT32 MrcSafeConfig:1; ///< Offset 64 MRC Safe Mode: <b>0=Disable</b>, 1=Enable
+ UINT32 EccSupport:1; ///< - DIMM Ecc Support option - for Desktop only: 0=Disable, <b>1=Enable</b>
+ UINT32 RemapEnable:1; ///< - This option is used to control whether to enable/disable memory remap above 4GB: 0=Disable, <b>1=Enable</b>.
+ UINT32 ScramblerEnable:1; ///< - Memory scrambler support: 0=Disable, <b>1=Enable</b>
+ UINT32 OddRatioMode:1; ///< - If Odd Ratio Mode is enabled, QCLK frequency has an addition of 133/100 MHz: <b>0=Disable</b>, 1=Enable
+ UINT32 MrcTimeMeasure:1; ///< - Enables serial debug level to display the MRC execution times only: <b>0=Disable</b>, 1=Enable
+ UINT32 MrcFastBoot:1; ///< - Enables the MRC fast boot path for faster cold boot execution: 0=Disable, <b>1=Enable</b>
+ UINT32 DqPinsInterleaved:1; ///< - Interleaving mode of DQ/DQS pins for HSW_ULT which depends on board routing: <b>0=Disable</b>, 1=Enable
+ UINT32 RankInterleave:1; ///< - Rank Interleave Mode: 0=Disable, <b>1=Enable</b>
+ UINT32 EnhancedInterleave:1; ///< - Enhanced Interleave Mode: 0=Disable, <b>1=Enable</b>
+ UINT32 WeaklockEn:1; ///< - Weak Lock Enable: 0=Disable, <b>1=Enable</b>
+ UINT32 CmdTriStateDis:1; ///< - CMD Tri-State Support: <b>0=Enable</b>, 1=Disable. Note: This should be set to 1 (Disable) if Command RTT is not present on the platform.
+ UINT32 MemoryTrace:1; ///< - Memory Trace to second DDR channel using Stacked Mode: <b>0=Disable</b>, 1=Enable
+ UINT32 ChHashEnable:1; ///< - Channel Hash Enable: 0=Disable, <b>1=Enable</b>
+ UINT32 EnableExtts:1; ///< - Enable Extts: <b>0=Disable</b>, 1=Enable
+ UINT32 EnableCltm:1; ///< - Enable Closed Loop Thermal Management: <b>0=Disable</b>, 1=Enable
+ UINT32 EnableOltm:1; ///< - Enable Open Loop Thermal Management: <b>0=Disable</b>, 1=Enable
+ UINT32 EnablePwrDn:1; ///< - Enable Power Down control for DDR: 0=PCODE control, <b>1=BIOS control</b>
+ UINT32 EnablePwrDnLpddr:1; ///< - Enable Power Down for LPDDR: 0=PCODE control, <b>1=BIOS control</b>
+ UINT32 LockPTMregs:1; ///< - Lock PCU Thermal Management registers: 0=Disable, <b>1=Enable</b>
+ UINT32 UserPowerWeightsEn:1; ///< - Allows user to explicitly set power weight, scale factor, and channel power floor values: <b>0=Disable</b>, 1=Enable
+ UINT32 RaplLim2Lock:1; ///< - Lock DDR_RAPL_LIMIT register: <b>0=Disable</b>, 1=Enable
+ UINT32 RaplLim2Ena:1; ///< - Enable Power Limit 2: <b>0=Disable</b>, 1=Enable
+ UINT32 RaplLim1Ena:1; ///< - Enable Power Limit 1: <b>0=Disable</b>, 1=Enable
+ UINT32 SrefCfgEna:1; ///< - Enable Self Refresh: 0=Disable, <b>1=Enable</b>
+ UINT32 ThrtCkeMinDefeatLpddr:1; ///< - Throttler CKE min defeature for LPDDR: 0=Disable, <b>1=Enable</b>
+ UINT32 ThrtCkeMinDefeat:1; ///< - Throttler CKE min defeature: <b>0=Disable</b>, 1=Enable
+ UINT32 AutoSelfRefreshSupport:1; ///< - FALSE = No auto self refresh support, <b>TRUE = auto self refresh support</b>
+ UINT32 ExtTemperatureSupport:1; ///< - FALSE = No extended temperature support, <b>TRUE = extended temperature support</b>
+ UINT32 MobilePlatform:1; ///< - Memory controller device id indicates: <b>TRUE if mobile</b>, FALSE if not. Note: This will be auto-detected and updated.
+ UINT32 Force1Dpc:1; ///< - TRUE means force one DIMM per channel, <b>FALSE means no limit</b>
+ UINT32 ForceSingleRank:1; ///< - TRUE means use Rank0 only (in each DIMM): <b>0=Disable</b>, 1=Enable
+
+ UINT32 RhPrevention:1; ///< Offset 68 RH Prevention Enable/Disable: 0=Disable, <b>1=Enable</b>
+ UINT32 VttTermination:1; ///< - Vtt Termination for Data ODT: <b>0=Disable</b>, 1=Enable
+ UINT32 VttCompForVsshi:1; ///< - Enable/Disable Vtt Comparator For Vsshi: <b>0=Disable</b>, 1=Enable
+ UINT32 ExitOnFailure:1; ///< - MRC option for exit on failure or continue on failure: 0=Disable, <b>1=Enable</b>
+ UINT32 Vc1ReadMeter:1; ///< - VC1 Read Metering Enable: 0=Disable, <b>1=Enable</b>
+ UINT32 DdrThermalSensor:1; ///< - Ddr Thermal Sensor: 0=Disable, <b>1=Enable</b>
+ UINT32 LpddrMemWriteLatencySet:1; ///< - LPDDR3 Write Latency Set option: 0=Set A, <b>1=Set B</b>
+ UINT32 EvLoader:1; ///< - Option to Enable EV Loader: <b>0=Disable</b>,1=Enable
+ UINT32 EvLoaderDelay:1; ///< - Option to Enable EV Loader Delay: 0=Disable, <b>1=Enable</b>
+ UINT32 Ddr4DdpSharedClock:1; ///< - Select if CLK0 is shared between Rank0 and Rank1 in DDR4 DDP package. <b>0=Not shared</b>, 1=Shared
+ UINT32 Ddr4DdpSharedZq:1; ///< - Select if ZQ pin is shared between Rank0 and Rank1 in DDR4 DDP package. <b>0=Not shared</b>, 1=Shared
+ UINT32 RsvdBits1:21;
+
+ UINT32 BClkFrequency; ///< Offset 72 - Base reference clock value, in Hertz: <b>100000000 = 100Hz</b>, 125000000=125Hz, 167000000=167Hz, 250000000=250Hz
+ UINT16 DdrFreqLimit; ///< Offset 76 Memory Frequency Limit: <b>0=Auto (limited by SPD/CPU capability)</b>, for valid values see MrcFrequency in MrcInterface.h
+ /**
+ Selects the DDR base reference clock\n
+ <b>0x00 = 133MHz</b>
+ 0x01 = 100MHz
+ **/
+ UINT8 RefClk; ///< Offset 78
+ /**
+ Selects the ratio to multiply the reference clock by for the DDR frequency\n
+ When RefClk is 133MHz\n
+ <b>0x00 = Auto</b>, 0x03 through 0x0C are valid values, all others are invalid\n
+ When RefClk is 100MHz\n
+ <b>0x00 = Auto</b>, 0x06 through 0x10 are valid values, all others are invalid\n
+ **/
+ UINT8 Ratio; ///< Offset 79
+ MrcGdxc Gdxc; ///< Offset 80 GDXC enable and size.
+ /**
+ - Channel Hash Enable.\n
+ NOTE: BIT7 will interlave the channels at a 2 cacheline granularity, BIT8 at 4 and BIT9 at 8\n
+ 0=BIT6, <B>1=BIT7</B>, 2=BIT8, 3=BIT9
+ **/
+ UINT8 ChHashInterleaveBit; ///< Offset 83
+ UINT16 ChHashMask; ///< Offset 84 - Channel Hash Mask: 0x0001=BIT6 set(Minimal), 0x3FFF=BIT[19:6] set(Maximum), <b>0x30CE= BIT[19:18, 13:12 ,9:7] set</b>
+ /**
+ Disables a DIMM slot in the channel even if a DIMM is present\n
+ Array index represents the channel number (0 = channel 0, 1 = channel 1)\n
+ <b>0x0 = DIMM 0 and DIMM 1 enabled</b>\n
+ 0x1 = DIMM 0 disabled, DIMM 1 enabled\n
+ 0x2 = DIMM 0 enabled, DIMM 1 disabled\n
+ 0x3 = DIMM 0 and DIMM 1 disabled (will disable the whole channel)\n
+ **/
+ UINT8 DisableDimmChannel[MAX_CHANNEL];///< Offset 86
+ ThermalMngmtEn ThermalEnables; ///< Offset 88
+
+ UINT16 SrefCfgIdleTmr; ///< Offset 132 - Self Refresh idle timer: <b>512=Minimal</b>, 65535=Maximum
+ UINT8 MaxRttWr; ///< Offset 134 - Maximum DIMM RTT_WR to use in power training: <b>0=ODT Off</b>, 1 = 120 ohms
+ UINT8 ThrtCkeMinTmr; ///< Offset 135 - Throttler CKE min timer: 0=Minimal, 0xFF=Maximum, <b>0x30=Default</b>
+ UINT8 ThrtCkeMinTmrLpddr; ///< Offset 136 - Throttler CKE min timer for LPDDR: 0=Minimal, 0xFF=Maximum, <b>0x40=Default</b>
+
+ UINT8 EnergyScaleFact; ///< Offset 137 - Energy Scale Factor. 0=Minimal, 7=Maximum, <b>4=Default</b>
+ UINT8 RaplPwrFlCh1; ///< Offset 138 - Power Channel 1 Floor value: <b>0=Minimal</b>, 255=Maximum
+ UINT8 RaplPwrFlCh0; ///< Offset 139 - Power Channel 0 Floor value: <b>0=Minimal</b>, 255=Maximum
+ UINT8 PowerDownMode; ///< Offset 140 - CKE Power Down Mode: <b>0xFF=AUTO</b>, 0=No Power Down, 1= APD mode, 6=PPD-DLL Off mode
+ UINT8 PwdwnIdleCounter; ///< Offset 141 - CKE Power Down Mode Idle Counter: 0=Minimal, 255=Maximum, <b>0x80=0x80 DCLK</b>
+ UINT8 CkeRankMapping; ///< Offset 142 - Bits [7:4] - Channel 1, bits [3:0] - Channel 0. <b>0xAA=Default</b> Bit [i] specifies which rank CKE[i] goes to.
+ UINT8 BerEnable; ///< Offset 143 - BER Enable and # of Addresses passed in: <b>0=Minimal</b>, 8=Maximum
+ UINT64 BerAddress[4]; ///< Offset 144 - BER Address(es): <b>0=Minimal</b>, 0xFFFFFFFFFFFFFFFF=Maximum (step is 0x40)
+ UINT16 PciIndex; ///< Offset 176 - Pci index register address: <b>0xCF8=Default</b>
+ UINT16 PciData; ///< Offset 178 - Pci data register address: <b>0xCFC=Default</b>
+
+ UINT8 StrongWkLeaker; ///< Offset 180 - Strong Weak Leaker: 1=Minimal, <b>7=Maximum</b>
+ UINT8 CaVrefConfig; ///< Offset 181 0=VREF_CA goes to both CH_A and CH_B, 1=VREF_CA to CH_A, VREF_DQ_A to CH_B, <b>2=VREF_CA to CH_A, VREF_DQ_B to CH_B</b>
+ UINT16 FreqSaGvLow; ///< Offset 182 SA GV Low: 0 is Auto/default, otherwise holds the frequency value: <b>0=Default</b>, 1067, 1200, 1333, 1400, 1600, 1800, 1867. NOTE: must be below or equal to the SA GV High frequency.
+ UINT32 Vc1ReadMeterTimeWindow; ///< Offset 184 - VC1 Read Meter Time Window: 0=Minimal, 0x1FFFF=Maximum, <b>0x320=Default</b>
+ UINT16 Vc1ReadMeterThreshold; ///< Offset 188 - VC1 Read Meter Threshold (within Time Window): 0=Minimal, 0xFFFF=Maximum, <b>0x118=Default</b>
+ UINT16 Idd3n; ///< Offset 190 EPG Active standby current (Idd3N) in milliamps from DIMM datasheet.
+ UINT16 Idd3p; ///< Offset 192 EPG Active power-down current (Idd3P) in milliamps from DIMM datasheet.
+ UINT8 EpgEnable; ///< Offset 194 Enable Energy Performance Gain.
+ UINT8 RhSolution; ///< Offset 195 Type of solution to be used for RHP - 0/1 = HardwareRhp/Refresh2x
+ UINT8 RhActProbability; ///< Offset 196 Activation probability for Hardware RHP
+ UINT8 SaGv; ///< Offset 197 SA GV: <b>0=Disabled</b>, 1=FixedLow, 2=FixedHigh, 3=Enabled
+
+ UINT8 UserThresholdEnable; ///< Offset 198 - Flag to manually select the DIMM CLTM Thermal Threshold, 0=Disable, 1=Enable, <b>0=Default</b>
+ UINT8 UserBudgetEnable; ///< Offset 199 - Flag to manually select the Budget Regiseters for CLTM Memory Dimms , 0=Disable, 1=Enable, <b>0=Default</b>
+ UINT8 TsodTcritMax; ///< Offset 200 - TSOD Tcrit Maximum Value to be Configure , 0=Minimal, 128=Maximum, , <b>105=Default</b>
+ UINT8 TsodEventMode; ///< Offset 201 - Flag to Enable Event Mode Interruption in TSOD Configuration Register, 0=Disable, 1=Enable, <b>1=Default</b>
+ UINT8 TsodEventPolarity; ///< Offset 202 - Event Signal Polarity in TSOD Configuration Register, 0=Low, 1=High, <b>0=Default</b>
+ UINT8 TsodCriticalEventOnly; ///< Offset 203 - Critical Trigger Only in TSOD Configuration Register,0=Disable, 1=Enable, <b>1=Default</b>
+ UINT8 TsodEventOutputControl; ///< Offset 204 - Event Output Control in TSOD Configuration Register,0=Disable, 1=Enable, <b>1=Default</b>
+ UINT8 TsodAlarmwindowLockBit; ///< Offset 205 - Alarm Windows Lock Bit in TSOD Configuration Register,0=Unlock, 1=Lock, <b>0=Default</b>
+ UINT8 TsodCriticaltripLockBit;///< Offset 206 - Critical Trip Lock Bit in TSOD Configuration Register,0=Unlock, 1=Lock, <b>0=Default</b>
+ UINT8 TsodShutdownMode; ///< Offset 207 - Shutdown Mode TSOD Configuration Register,0=Enable, 1=Disable, <b>0=Default</b>
+ UINT8 TsodThigMax; ///< Offset 208 - Thigh Max Value In the for CLTM Memory Dimms , 0=Disable, 1=Enable, <b>0=Default</b>
+ UINT8 TsodManualEnable; ///< Offset 209 - Flag to manually select the TSOD Register Values , 0=Disable, 1=Enable, <b>0=Default</b>
+
+ UINT8 RetrainOnFastFail; ///< Offset 210 - Restart MRC in Cold mode if SW MemTest fails during Fast flow. 0 = Disabled, <b>1 = Enabled</b>
+ UINT8 ForceOltmOrRefresh2x; ///< Offset 211 - Force OLTM or 2X Refresh when needed. <b>0 = Force OLTM</b>, 1 = Force 2x Refresh
+ UINT8 DllBwEn0; ///< Offset 212 - DllBwEn value for 1067
+ UINT8 DllBwEn1; ///< Offset 213 - DllBwEn value for 1333
+ UINT8 DllBwEn2; ///< Offset 214 - DllBwEn value for 1600
+ UINT8 DllBwEn3; ///< Offset 215 - DllBwEn value for 1867 and up
+ UINT32 VddSettleWaitTime; ///< Offset 216 - Amount of time in microseconds to wait for Vdd to settle on top of 200us required by JEDEC spec: <b>Default=0</b>
+ UINT8 EnCmdRate; ///< Offset 220 - CMD Rate Enable: 0=Disable, 1=1 CMD, 2=2 CMDs, <b>3=3 CMDs</b>, 4=4 CMDs, 5=5 CMDs, 6=6 CMDs, 7=7 CMDs
+ UINT8 Refresh2X; ///< Offset 221 - Refresh 2x: <b>0=Disable</b>, 1=Enable for WARM or HOT, 2=Enable for HOT only
+ UINT8 SmramMask; ///< Offset 222 Reserved memory ranges for SMRAM
+ UINT8 Rsvd0; ///< Offset 223 - Reserved.
+
+ TrainingStepsEn2 TrainingEnables2; ///< Offset 224 - Options to Enable individual training steps
+ //
+ // End of synchronization to the SA MEMORY_CONFIGURATION structure.
+ //
+ MrcFrequency FreqMax; ///< The requested maximum valid frequency.
+ MrcBoardType BoardType; ///< define the board type (CRBMB,CRBDT,User1,User2). the OEM can add more boards.
+ MrcCpuStepping CpuStepping; ///< define the CPU stepping.
+ MrcCpuModel CpuModel; ///< define the CPU model.
+ MrcCpuFamily CpuFamily; ///< CPU is Skylake or Kabylake
+ MrcGfxDataSize GraphicsStolenSize; ///< Graphics Data Stolen Memory size in MB
+ MrcGfxGttSize GraphicsGttSize; ///< GTT graphics stolen memory size in MB
+ MrcBaseTime BaseTime; ///< RTC base time.
+ MrcIteration Iteration; ///< Number of interations thru the MRC core call table.
+ MrcMode MrcMode; ///< The control for full or MiniBIOS MRC.
+ MrcBootMode BootMode; ///< The requested memory controller boot mode.
+ BOOLEAN TxtFlag; ///< Trusted eXecution Technology flag.
+ BOOLEAN SetRxDqs32; ///< Set DQS Delay to 32 control.
+ BOOLEAN GfxIsVersatileAcceleration; ///< iGFX engines are in Versatile Acceleration
+ BOOLEAN DDR4MAP; ///< DDR4 PDA Mapping training control.
+ UINT32 SaMemCfgAddress; ///< Starting address of the input parameters to CRC.
+ UINT32 SaMemCfgSize; ///< The size of the input parameters to CRC.
+ UINT32 PciEBaseAddress; ///< define the PciE base address.
+ UINT32 MchBarBaseAddress; ///< define the MCH bar base address.
+ UINT32 SmbusBaseAddress; ///< This field defines the smbus base address.
+ UINT32 GdxcBaseAddress; ///< This field defines the GDXC base address.
+ UINT32 HpetBaseAddress; ///< This field defines the hpet base address.
+ UINT32 MeStolenSize; ///< define the size that the ME need in MB.
+ UINT32 MmioSize; ///< define the MMIO size in MB.
+ UINT32 TsegSize; ///< TSEG size that require by the system in MB.
+ UINT32 IedSize; ///< IED size that require by the system in MB.
+ UINT32 DprSize; ///< DPR size required by system in MB.
+ UINT32 PrmrrSize; ///< Prmrr size required by the system in MB.
+ UINT32 SerialBuffer; ///< Pointer to the start of the serial buffer.
+ UINT32 SerialBufferSize; ///< The size of the serial buffer, in bytes.
+ UINT32 DebugStream; ///< The debug port pointer.
+ UINT32 MmaTestContentPtr; ///< Pointer to MMA Test Content Data. Used in FSP.
+ UINT32 MmaTestContentSize; ///< Size of MMA Test Content Data. Used in FSP.
+ UINT32 MmaTestConfigPtr; ///< Pointer to MMA Test Config Data. Used in FSP.
+ UINT32 MmaTestConfigSize; ///< Size of MMA Test Config Data. Used in FSP.
+ INT32 DebugLevel; ///< Indicates the level of debug messaging.
+ UINT16 VccIomV; ///< VccIO logic voltage in mV.
+ MrcControllerIn Controller[MAX_CONTROLLERS]; ///< The following are controller level definitions.
+ BOOLEAN RmtPerTask; ///< Option to enable RMT after major training steps
+#ifdef SSA_FLAG
+ UINT32 SsaCallbackPpi;
+#endif // SSA_FLAG
+ UINT32 HeapBase; ///< Starting address of the heap space.
+ UINT32 HeapSize; ///< Size of the heap space, in bytes.
+ UINT32 MrcStackTop; ///< Top of the stack at the beginning of MRC, for stack usage calculations.
+ BOOLEAN RmtBdatEnable; ///< Option to enable output of training results into BDAT.
+ BOOLEAN LpddrDramOdt; ///< TRUE if LPDDR DRAM ODT is used - depends on board design
+ BOOLEAN Ddr3DramOdt; ///< TRUE if DDR3 DRAM ODT is used - depends on board design
+ BOOLEAN Ddr4DramOdt; ///< TRUE if DDR4 DRAM ODT is used - depends on board design
+ BOOLEAN EnableVrefPwrDn; ///< Setting this limits VrefGen to be off only during CKEPowerDown
+ BOOLEAN TxEqDis; ///< Disable TX Equalization
+ BOOLEAN EnVttOdt; ///< Enable VTT Termination for Data ODT
+ UINT32 CpuidModel; ///< Unique CPU identifier.
+ UINT8 CpuidStepping; ///< Revision of the CPU.
+ UINT32 SiPreMemPolicyPpi;
+ TrainingModeType PowerTrainingMode; ///< 0 - Power Training. 1 - Margin Training.
+ union {
+ MRC_FUNCTION *Func; ///< External to MRC function pointers
+ UINT64 Data;
+ } Call;
+ UINT16 RcompResistor[MAX_RCOMP]; ///< Reference RCOMP resistors on motherboard
+ UINT16 RcompTarget[MAX_RCOMP_TARGETS]; ///< RCOMP target values for DqOdt, DqDrv, CmdDrv, CtlDrv, ClkDrv
+ UINT32 CleanMemory:1; ///< TRUE to request a memory clean
+ UINT32 RsvdBits5:31;
+ /**
+ Sets the serial debug message level\n
+ 0x00 = Disabled\n
+ 0x01 = Errors only\n
+ 0x02 = Errors and Warnings\n
+ <b>0x03 = Errors, Warnings, and Info</b>\n
+ 0x04 = Errors, Warnings, Info, and Events\n
+ 0x05 = Displays Memory Init Execution Time Summary only\n
+ **/
+ UINT8 SerialDebugLevel; ///<
+} MrcInput;
+
+typedef struct {
+ UINT32 Size; ///< The size of this structure, in bytes. Must be the first entry in this structure.
+ MrcSaveHeader Header; ///< The header portion of the MRC saved data.
+ MrcSaveData Data; ///< The data portion of the MRC saved data.
+} MrcSave;
+
+typedef struct {
+ // Global variables that will be copied to the HOB follow.
+ UINT8 MrcDataString[4]; ///< Beginning of global data marker, starts with "MRC". Must be the first entry in this structure.
+ UINT32 MrcDataSize; ///< The size of the MRC global data area, in bytes. Must be the second entry in this structure.
+ MrcSave Save; ///< System specific save variables.
+ MrcInput Inputs; ///< System specific input variables.
+ MrcOutput Outputs; ///< System specific output variables.
+
+ // Global variables that will remain internal to the MRC library follow.
+ union {
+ void *Internal; ///< System specific output variables that remain internal to the library.
+ UINT64 Data;
+ } IntOutputs;
+} MrcParameters;
+
+/**
+ This function returns the recommended MRC boot mode.
+
+ @param[in] MrcData - include all the MRC general data.
+
+ @retval bmWarm if we are in self refresh and the DISB bit is set, otherwise returns bmCold.
+**/
+extern
+MrcBootMode
+MrcGetBootMode (
+ IN MrcParameters * const MrcData
+ );
+
+/**
+ This function return the MRC version.
+
+ @param[in] MrcData - include all the MRC general data.
+ @param[out] Version - Location to store the MRC version.
+**/
+extern
+void
+MrcVersionGet (
+ IN const MrcParameters *const MrcData,
+ OUT MrcVersion *const Version
+ );
+
+/**
+ Print the MRC version to the MRC output device.
+
+ @param[in] *MrcData - Pointer to the MRC Debug structure.
+ @param[in] Version - The MRC version.
+**/
+extern
+void
+MrcVersionPrint (
+ IN MrcParameters *MrcData,
+ IN const MrcVersion *Version
+ );
+
+/**
+ Calculates a CRC-32 of the specified data buffer.
+
+ @param[in] Data - Pointer to the data buffer.
+ @param[in] DataSize - Size of the data buffer, in bytes.
+
+ @retval The CRC-32 value.
+**/
+extern
+UINT32
+MrcCalculateCrc32 (
+ IN const UINT8 *const Data,
+ IN const UINT32 DataSize
+ );
+
+/**
+ This function resets the DISB bit in General PM Configuration 2 B:D:F 0,31,0 offset 0xA2.
+
+ @param[in] MrcData - include all the MRC general data.
+**/
+extern
+void
+MrcResetDISB (
+ IN MrcParameters * const MrcData
+ );
+
+/**
+ Initializes the memory controller and DIMMs.
+
+ @param[in, out] MrcData - Include all MRC global data.
+ @param[in] Select - Specific task index to execute, or zero to run all tasks from the call table.
+ Used in the interpreter.
+
+ @retval mrcSuccess if the initialization succeeded, otherwise an error status indicating the failure.
+**/
+extern
+MrcStatus
+MrcStartMemoryConfiguration (
+ IN OUT MrcParameters *const MrcData,
+ IN UINT32 Select
+ );
+
+/**
+ Retrieve the current memory frequency and clock from the memory controller.
+
+ @param[in] MrcData - Include all MRC global data.
+ @param[in, out] MemoryClock - The current memory clock.
+ @param[in, out] Ratio - The current memory ratio setting.
+ @param[in, out] RefClk - The current memory reference clock.
+ @param[in, out] OddRatioMode - The current QCLK Odd Ratio mode.
+
+ @retval: The current memory frequency.
+**/
+MrcFrequency
+MrcGetCurrentMemoryFrequency (
+ MrcParameters * const MrcData,
+ UINT32 * const MemoryClock,
+ MrcClockRatio * const Ratio,
+ MrcRefClkSelect * const RefClk,
+ BOOLEAN * const OddRatioMode
+ );
+
+/**
+ This function get the current value of the sticky scratchpad register.
+
+ @param[in] MrcData - include all the MRC data.
+
+ @retval The current value of the sticky scratchpad register.
+
+ **/
+extern
+UINT64
+MrcWmRegGet (
+ IN MrcParameters *const MrcData
+ );
+
+/**
+ This function reads the current setting of the GDXC MOT region.
+
+ @param[in] MrcData - All the MRC global data.
+ @param[in, out] Start - The starting GDXC MOT address.
+ @param[in, out] End - The ending GDXC MOT address.
+
+ @retval Returns mrcSuccess if the value has been read.
+**/
+extern
+MrcStatus
+MrcGetGdxcMot (
+ IN MrcParameters *const MrcData,
+ IN OUT UINT32 *const Start,
+ IN OUT UINT32 *const End
+ );
+
+/**
+ This function reads the current setting of the GDXC OCLA region.
+
+ @param[in] MrcData - All the MRC global data.
+ @param[in, out] Start - The starting GDXC MOT address.
+ @param[in, out] End - The ending GDXC MOT address.
+
+ @retval Returns mrcSuccess if the value has been read.
+**/
+extern
+MrcStatus
+MrcGetGdxcOcla (
+ IN MrcParameters *const MrcData,
+ IN OUT UINT32 *const Start,
+ IN OUT UINT32 *const End
+ );
+
+/**
+ Gets pointers to functions inside of core.
+
+ @param[in] MrcData - All the MRC global data.
+ @param[out] CallMcAddressDecode - Pointer to the function MrcMcAddressDecode
+ @param[out] CallMcAddressEncode - Pointer to the function MrcMcAddressEncode
+ @param[out] CallChannelExist - Pointer to the function MrcChannelExist
+ @param[out] CallPrintf - Pointer to the function MrcPrintf
+ @param[out] CallChangeMargin - Pointer to the function ChangeMargin
+ @param[out] CallSignExtend - Pointer to the function MrcSignExtend
+ @param[out] CallShiftPIforCmdTraining - Pointer to the function ShiftPIforCmdTraining
+ @param[out] CallUpdateVrefWaitTilStable - Pointer to the function UpdateVrefWaitTilStable
+ @param[out] CallMrcThermalOverrides - Pointer to the function MrcThermalOverrides
+
+ @retval Returns mrcSuccess if the function succeeds.
+**/
+extern
+MrcStatus
+MrcGetCoreFunction (
+ IN const MrcParameters *const MrcData,
+ OUT UINT32 *CallMcAddressDecode,
+ OUT UINT32 *CallMcAddressEncode,
+ OUT UINT32 *CallChannelExist,
+ OUT UINT32 *CallPrintf,
+ OUT UINT32 *CallChangeMargin,
+ OUT UINT32 *CallSignExtend,
+ OUT UINT32 *CallShiftPIforCmdTraining,
+ OUT UINT32 *CallUpdateVrefWaitTilStable,
+ OUT UINT32 *CallMrcThermalOverrides
+ );
+
+
+/**
+ Set up the overrides required by the MiniBios execution.
+
+ @param[in] MrcData - Pointer to the MRC global data structure
+**/
+extern
+void
+MrcMiniBiosOverrides (
+ OUT MrcParameters *const MrcData
+ );
+
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcRmtData.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcRmtData.h
new file mode 100644
index 0000000000..51d40ff376
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcRmtData.h
@@ -0,0 +1,237 @@
+/** @file
+ Copies the memory related timing and configuration information into the
+ Compatible BIOS data (BDAT) table.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MrcRmtData_h_
+#define _MrcRmtData_h_
+
+#include "MrcTypes.h"
+
+#define VDD_1_350 1350 ///< VDD in millivolts
+#define VDD_1_500 1500 ///< VDD in millivolts
+#define PI_STEP_BASE 2048 ///< Magic number from spec
+#define PI_STEP_INTERVAL 128 ///< tCK is split into this amount of intervals
+#define PI_STEP ((PI_STEP_BASE) / (PI_STEP_INTERVAL))
+#define VREF_STEP_BASE 100 ///< Magic number from spec
+#define TX_VREF_STEP 7800 ///< TX Vref step in microvolts
+#define TX_VREF(VDD) (((TX_VREF_STEP) * (VREF_STEP_BASE)) / (VDD)) ///< VDD passed in is in millivolts
+#define RX_VREF_STEP 8000 ///< TX Vref step in microvolts
+#define RX_VREF(VDD) (((RX_VREF_STEP) * (VREF_STEP_BASE)) / (VDD)) ///< VDD passed in is in millivolts
+#define CA_VREF_STEP 8000 ///< TX Vref step in microvolts
+#define CA_VREF(VDD) (((CA_VREF_STEP) * (VREF_STEP_BASE)) / (VDD)) ///< VDD passed in is in millivolts
+
+#define MAX_SPD_RMT 512 ///< The maximum amount of data, in bytes, in an SPD structure.
+#define RMT_PRIMARY_VERSION 4 ///< The BDAT structure that is currently supported.
+#define RMT_SECONDARY_VERSION 0 ///< The BDAT structure that is currently supported.
+#define MAX_MODE_REGISTER 7 ///< Number of mode registers
+#define MAX_DRAM_DEVICE 9 ///< Maximum number of memory devices
+
+//
+// Warning: Bdat4.h has its own copy of this #define
+// make sure to change it in both places
+//
+#define MAX_SCHEMA_LIST_LENGTH (10)
+
+/*
+ Memory Schema GUID
+ This is private GUID used by MemoryInit internally.
+ {CE3F6794-4883-492C-8DBA-2FC098447710}
+*/
+#ifdef BDAT_SUPPORT
+extern EFI_GUID gEfiMemorySchemaGuid;
+#endif
+/*
+ GUID for Schema List HOB
+ This is private GUID used by MemoryInit internally.
+ {3047C2AC-5E8E-4C55-A1CB-EAAD0A88861B}
+*/
+extern EFI_GUID gMrcSchemaListHobGuid;
+
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT8 RxDqLeft; ///< Units = piStep
+ UINT8 RxDqRight;
+ UINT8 TxDqLeft;
+ UINT8 TxDqRight;
+ UINT8 RxVrefLow; ///< Units = rxVrefStep
+ UINT8 RxVrefHigh;
+ UINT8 TxVrefLow; ///< Units = txVrefStep
+ UINT8 TxVrefHigh;
+} BDAT_DQ_MARGIN_STRUCTURE;
+
+typedef struct {
+ UINT8 RxDqLeft; ///< Units = piStep
+ UINT8 RxDqRight;
+ UINT8 TxDqLeft;
+ UINT8 TxDqRight;
+ UINT8 CmdLeft;
+ UINT8 CmdRight;
+ UINT8 RecvenLeft; ///< Units = recvenStep
+ UINT8 RecvenRight;
+ UINT8 WrLevelLeft; ///< Units = wrLevelStep
+ UINT8 WrLevelRight;
+ UINT8 RxVrefLow; ///< Units = rxVrefStep
+ UINT8 RxVrefHigh;
+ UINT8 TxVrefLow; ///< Units = txVrefStep
+ UINT8 TxVrefHigh;
+ UINT8 CmdVrefLow; ///< Units = caVrefStep
+ UINT8 CmdVrefHigh;
+} BDAT_RANK_MARGIN_STRUCTURE;
+
+typedef struct {
+ UINT16 RecEnDelay[MAX_STROBE];
+ UINT16 WlDelay[MAX_STROBE];
+ UINT8 RxDqDelay[MAX_STROBE];
+ UINT8 TxDqDelay[MAX_STROBE];
+ UINT8 ClkDelay;
+ UINT8 CtlDelay;
+ UINT8 CmdDelay[3];
+ UINT8 IoLatency;
+ UINT8 Roundtrip;
+} BDAT_RANK_TRAINING_STRUCTURE;
+
+typedef struct {
+ UINT16 ModeRegister[MAX_MODE_REGISTER]; ///< Mode register settings
+} BDAT_DRAM_MRS_STRUCTURE;
+
+typedef struct {
+ UINT8 RankEnabled; ///< 0 = Rank disabled
+ UINT8 RankMarginEnabled; ///< 0 = Rank margin disabled
+ UINT8 DqMarginEnabled; ///< 0 = Dq margin disabled
+ BDAT_RANK_MARGIN_STRUCTURE RankMargin; ///< Rank margin data
+ BDAT_DQ_MARGIN_STRUCTURE DqMargin[MAX_DQ]; ///< Array of Dq margin data per rank
+ BDAT_RANK_TRAINING_STRUCTURE RankTraining; ///< Rank training settings
+ BDAT_DRAM_MRS_STRUCTURE RankMRS[MAX_DRAM_DEVICE]; ///< Rank MRS settings
+} BDAT_RANK_STRUCTURE;
+
+typedef struct {
+ UINT8 SpdValid[MAX_SPD_RMT / (CHAR_BITS * sizeof (UINT8))]; ///< Each valid bit maps to SPD byte
+ UINT8 SpdData[MAX_SPD_RMT]; ///< Array of raw SPD data bytes
+} BDAT_SPD_STRUCTURE;
+
+typedef struct {
+ UINT8 DimmEnabled; ///< 0 = DIMM disabled
+ BDAT_RANK_STRUCTURE RankList[MAX_RANK_IN_DIMM]; ///< Array of ranks per DIMM
+ BDAT_SPD_STRUCTURE SpdBytes; ///< SPD data per DIMM
+} BDAT_DIMM_STRUCTURE;
+
+typedef struct {
+ UINT8 ChannelEnabled; ///< 0 = Channel disabled
+ UINT8 NumDimmSlot; ///< Number of slots per channel on the board
+ BDAT_DIMM_STRUCTURE DimmList[MAX_DIMMS_IN_CHANNEL]; ///< Array of DIMMs per channel
+} BDAT_CHANNEL_STRUCTURE;
+
+typedef struct {
+ UINT8 ControllerEnabled; ///< 0 = MC disabled
+ UINT16 ControllerDeviceId; ///< MC device Id
+ UINT8 ControllerRevisionId; ///< MC revision Id
+ UINT16 MemoryFrequency; ///< Memory frequency in units of MHz / 10
+ ///< e.g. ddrFreq = 13333 for tCK = 1.5 ns
+ UINT16 MemoryVoltage; ///< Memory Vdd in units of mV
+ ///< e.g. ddrVoltage = 1350 for Vdd = 1.35 V
+ UINT8 PiStep; ///< Step unit = piStep * tCK / 2048
+ ///< e.g. piStep = 16 for step = 11.7 ps (1/128 tCK)
+ UINT16 RxVrefStep; ///< Step unit = rxVrefStep * Vdd / 100
+ ///< e.g. rxVrefStep = 520 for step = 7.02 mV
+ UINT16 TxVrefStep; ///< Step unit = txVrefStep * Vdd / 100
+ UINT16 CaVrefStep; ///< Step unit = caVrefStep * Vdd / 100
+ UINT8 RecvenStep; ///< Step unit = recvenStep * tCK / 2048
+ UINT8 WrLevelStep; ///< Step unit = wrLevelStep * tCK / 2048
+ BDAT_CHANNEL_STRUCTURE ChannelList[MAX_CHANNEL]; ///< Array of channels per memory controller
+} BDAT_SOCKET_STRUCTURE;
+
+typedef struct {
+ union {
+ UINT32 Data32; ///< MRC version: Major.Minor.Revision.Build
+ struct {
+ UINT8 Build; ///< MRC version: Build
+ UINT8 Revision; ///< MRC version: Revision
+ UINT8 Minor; ///< MRC version: Minor
+ UINT8 Major; ///< MRC version: Major
+ } Version;
+ } RefCodeRevision; ///< Major.Minor.Revision.Build
+ UINT8 MaxController; ///< Max controllers per system, e.g. 1
+ UINT8 MaxChannel; ///< Max channels per memory controller, e.g. 2
+ UINT8 MaxDimm; ///< Max DIMM per channel, e.g. 2
+ UINT8 MaxRankDimm; ///< Max ranks per DIMM, e.g. 2
+ UINT8 MaxStrobe; ///< Number of Dqs used by the rank, e.g. 18
+ UINT8 MaxDq; ///< Number of Dq bits used by the rank, e.g. 72
+ UINT32 MarginLoopCount; ///< Units of cache line
+ BDAT_SOCKET_STRUCTURE ControllerList[MAX_CONTROLLERS]; ///< Array of memory controllers per system
+} BDAT_SYSTEM_STRUCTURE;
+
+typedef struct {
+ UINT32 Data1;
+ UINT16 Data2;
+ UINT16 Data3;
+ UINT8 Data4[8];
+} BDAT_EFI_GUID;
+
+typedef struct {
+ UINT16 HobType;
+ UINT16 HobLength;
+ UINT32 Reserved;
+} BDAT_HOB_GENERIC_HEADER;
+
+typedef struct {
+ BDAT_HOB_GENERIC_HEADER Header;
+ BDAT_EFI_GUID Name;
+ ///
+ /// Guid specific data goes here
+ ///
+} BDAT_HOB_GUID_TYPE;
+
+typedef struct {
+ BDAT_EFI_GUID SchemaId; ///< The GUID uniquely identifies the format of the data contained within the structure.
+ UINT32 DataSize; ///< The total size of the memory block, including both the header as well as the schema specific data.
+ UINT16 Crc16; ///< Crc16 is computed in the same manner as the field in the BDAT_HEADER_STRUCTURE.
+} MRC_BDAT_SCHEMA_HEADER_STRUCTURE;
+
+typedef struct {
+ MRC_BDAT_SCHEMA_HEADER_STRUCTURE SchemaHeader; ///< The schema header.
+ union {
+ UINT32 Data; ///< MRC version: Major.Minor.Revision.Build
+ struct {
+ UINT8 Build; ///< MRC version: Build
+ UINT8 Revision; ///< MRC version: Revision
+ UINT8 Minor; ///< MRC version: Minor
+ UINT8 Major; ///< MRC version: Major
+ } Version;
+ } RefCodeRevision; ///< Major.Minor.Revision.Build
+ UINT8 MaxController; ///< Max controllers per system, e.g. 1
+ UINT8 MaxChannel; ///< Max channels per memory controller, e.g. 2
+ UINT8 MaxDimm; ///< Max DIMM per channel, e.g. 2
+ UINT8 MaxRankDimm; ///< Max ranks per DIMM, e.g. 2
+ UINT8 MaxStrobe; ///< Number of Dqs used by the rank, e.g. 18
+ UINT8 MaxDq; ///< Number of Dq bits used by the rank, e.g. 72
+ UINT32 MarginLoopCount; ///< Units of cache line
+ BDAT_SOCKET_STRUCTURE ControllerList[MAX_CONTROLLERS]; ///< Array of memory controllers per system
+} BDAT_MEMORY_DATA_STRUCTURE;
+
+typedef struct {
+ BDAT_HOB_GUID_TYPE HobGuidType;
+ BDAT_MEMORY_DATA_STRUCTURE MemorySchema;
+} BDAT_MEMORY_DATA_HOB;
+
+#pragma pack (pop)
+
+typedef struct {
+ BDAT_HOB_GUID_TYPE HobGuidType;
+ UINT16 SchemaHobCount;
+ UINT16 Reserved;
+ BDAT_EFI_GUID SchemaHobGuids[MAX_SCHEMA_LIST_LENGTH];
+} MRC_BDAT_SCHEMA_LIST_HOB;
+
+#endif //_MrcRmtData_h_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcSpdData.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcSpdData.h
new file mode 100644
index 0000000000..cbfeb1cd0a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcSpdData.h
@@ -0,0 +1,1173 @@
+/** @file
+ SPD data format header file.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _MrcSpdData_h_
+#define _MrcSpdData_h_
+#pragma pack (push, 1)
+
+#include "MrcTypes.h"
+
+#define MAX_XMP_PROFILES (2)
+#define SPD3_MANUF_SIZE (SPD3_MANUF_END - SPD3_MANUF_START + 1) ///< The size of the SPD manufacturing data.
+#define SPD4_MANUF_SIZE (SPD4_MANUF_END - SPD4_MANUF_START + 1) ///< The size of the SPD manufacturing data.
+#define SPDLP_MANUF_SIZE (SPDLP_MANUF_END - SPDLP_MANUF_START + 1) ///< The size of the SPD manufacturing data
+
+typedef union {
+ struct {
+ UINT8 BytesUsed : 4; ///< Bits 3:0
+ UINT8 BytesTotal : 3; ///< Bits 6:4
+ UINT8 CrcCoverage : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_DEVICE_DESCRIPTION_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Minor : 4; ///< Bits 3:0
+ UINT8 Major : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_REVISION_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Type : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_DRAM_DEVICE_TYPE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 ModuleType : 4; ///< Bits 3:0
+ UINT8 : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_MODULE_TYPE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Density : 4; ///< Bits 3:0
+ UINT8 BankAddress : 3; ///< Bits 6:4
+ UINT8 : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_SDRAM_DENSITY_BANKS_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 ColumnAddress : 3; ///< Bits 2:0
+ UINT8 RowAddress : 3; ///< Bits 5:3
+ UINT8 : 2; ///< Bits 7:6
+ } Bits;
+ UINT8 Data;
+} SPD_SDRAM_ADDRESSING_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 OperationAt1_50 : 1; ///< Bits 0:0
+ UINT8 OperationAt1_35 : 1; ///< Bits 1:1
+ UINT8 OperationAt1_25 : 1; ///< Bits 2:2
+ UINT8 : 5; ///< Bits 7:3
+ } Bits;
+ UINT8 Data;
+} SPD_MODULE_NOMINAL_VOLTAGE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 SdramDeviceWidth : 3; ///< Bits 2:0
+ UINT8 RankCount : 3; ///< Bits 5:3
+ UINT8 : 2; ///< Bits 7:6
+ } Bits;
+ UINT8 Data;
+} SPD_MODULE_ORGANIZATION_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 PrimaryBusWidth : 3; ///< Bits 2:0
+ UINT8 BusWidthExtension : 2; ///< Bits 4:3
+ UINT8 : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD_MODULE_MEMORY_BUS_WIDTH_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Divisor : 4; ///< Bits 3:0
+ UINT8 Dividend : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_FINE_TIMEBASE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Dividend : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_MEDIUM_TIMEBASE_DIVIDEND_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Divisor : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_MEDIUM_TIMEBASE_DIVISOR_STRUCT;
+
+typedef struct {
+ SPD_MEDIUM_TIMEBASE_DIVIDEND_STRUCT Dividend; ///< Medium Timebase (MTB) Dividend
+ SPD_MEDIUM_TIMEBASE_DIVISOR_STRUCT Divisor; ///< Medium Timebase (MTB) Divisor
+} SPD_MEDIUM_TIMEBASE;
+
+typedef union {
+ struct {
+ UINT8 tCKmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TCK_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT16 CL4 : 1; ///< Bits 0:0
+ UINT16 CL5 : 1; ///< Bits 1:1
+ UINT16 CL6 : 1; ///< Bits 2:2
+ UINT16 CL7 : 1; ///< Bits 3:3
+ UINT16 CL8 : 1; ///< Bits 4:4
+ UINT16 CL9 : 1; ///< Bits 5:5
+ UINT16 CL10 : 1; ///< Bits 6:6
+ UINT16 CL11 : 1; ///< Bits 7:7
+ UINT16 CL12 : 1; ///< Bits 8:8
+ UINT16 CL13 : 1; ///< Bits 9:9
+ UINT16 CL14 : 1; ///< Bits 10:10
+ UINT16 CL15 : 1; ///< Bits 11:11
+ UINT16 CL16 : 1; ///< Bits 12:12
+ UINT16 CL17 : 1; ///< Bits 13:13
+ UINT16 CL18 : 1; ///< Bits 14:14
+ UINT16 : 1; ///< Bits 15:15
+ } Bits;
+ UINT16 Data;
+ UINT8 Data8[2];
+} SPD_CAS_LATENCIES_SUPPORTED_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tAAmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TAA_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tWRmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TWR_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRCDmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRCD_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRRDmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRRD_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRPmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRP_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRPab : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRP_AB_MTB_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tRPabFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TRP_AB_FTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRPpb : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRP_PB_MTB_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tRPpbFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TRP_PB_FTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT16 tRFCab : 16; ///< Bits 15:0
+ } Bits;
+ UINT16 Data;
+ UINT8 Data8[2];
+} SPD_TRFC_AB_MTB_STRUCT;
+
+typedef union {
+struct {
+ UINT16 tRFCpb : 16; ///< Bits 15:0
+ } Bits;
+ UINT16 Data;
+ UINT8 Data8[2];
+} SPD_TRFC_PB_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRASminUpper : 4; ///< Bits 3:0
+ UINT8 tRCminUpper : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_TRAS_TRC_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRASmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRAS_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRCmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRC_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT16 tRFCmin : 16; ///< Bits 15:0
+ } Bits;
+ UINT16 Data;
+ UINT8 Data8[2];
+} SPD_TRFC_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tWTRmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TWTR_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tRTPmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TRTP_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tFAWminUpper : 4; ///< Bits 3:0
+ UINT8 : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_TFAW_MIN_MTB_UPPER_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tFAWmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TFAW_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tCWLmin : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_TCWL_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 NMode : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_SYSTEM_COMMAND_RATE_STRUCT;
+
+typedef union {
+ struct {
+ UINT16 tREFImin : 16; ///< Bits 15:0
+ } Bits;
+ UINT16 Data;
+ UINT8 Data8[2];
+} SPD_TREFI_MIN_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 RZQ6 : 1; ///< Bits 0:0
+ UINT8 RZQ7 : 1; ///< Bits 1:1
+ UINT8 : 5; ///< Bits 6:2
+ UINT8 DllOff : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_SDRAM_OPTIONAL_FEATURES_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 ExtendedTemperatureRange : 1; ///< Bits 0:0
+ UINT8 ExtendedTemperatureRefreshRate : 1; ///< Bits 1:1
+ UINT8 AutoSelfRefresh : 1; ///< Bits 2:2
+ UINT8 OnDieThermalSensor : 1; ///< Bits 3:3
+ UINT8 : 3; ///< Bits 6:4
+ UINT8 PartialArraySelfRefresh : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_SDRAM_THERMAL_REFRESH_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 ThermalSensorAccuracy : 7; ///< Bits 6:0
+ UINT8 ThermalSensorPresence : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_MODULE_THERMAL_SENSOR_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 NonStandardDeviceDescription : 7; ///< Bits 6:0
+ UINT8 SdramDeviceType : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_SDRAM_DEVICE_TYPE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_AUTO_SELF_REFRESH_PERF_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tCKminFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TCK_MIN_FTB_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tAAminFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TAA_MIN_FTB_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tRCDminFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TRCD_MIN_FTB_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tRPminFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TRP_MIN_FTB_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tRCminFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TRC_MIN_FTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tMACencoding : 4; ///< Bits 3:0
+ UINT8 tMAWencoding : 2; ///< Bits 5:4
+ UINT8 Reserved : 2; ///< Bits 7:6
+ } Bits;
+ UINT8 Data;
+} SPD_PTRR_SUPPORT_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tRRDminFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_TRRD_MIN_FTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Height : 5; ///< Bits 4:0
+ UINT8 RawCardExtension : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD_UNBUF_MODULE_NOMINAL_HEIGHT;
+
+typedef union {
+ struct {
+ UINT8 FrontThickness : 4; ///< Bits 3:0
+ UINT8 BackThickness : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_UNBUF_MODULE_NOMINAL_THICKNESS;
+
+typedef union {
+ struct {
+ UINT8 Card : 5; ///< Bits 4:0
+ UINT8 Revision : 2; ///< Bits 6:5
+ UINT8 Extension : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_UNBUF_REFERENCE_RAW_CARD;
+
+typedef union {
+ struct {
+ UINT8 MappingRank1 : 1; ///< Bits 0:0
+ UINT8 : 7; ///< Bits 7:1
+ } Bits;
+ UINT8 Data;
+} SPD_UNBUF_ADDRESS_MAPPING;
+
+typedef union {
+ struct {
+ UINT8 Height : 5; ///< Bits 4:0
+ UINT8 : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD_RDIMM_MODULE_NOMINAL_HEIGHT;
+
+typedef union {
+ struct {
+ UINT8 FrontThickness : 4; ///< Bits 3:0
+ UINT8 BackThickness : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_RDIMM_MODULE_NOMINAL_THICKNESS;
+
+typedef union {
+ struct {
+ UINT8 Card : 5; ///< Bits 4:0
+ UINT8 Revision : 2; ///< Bits 6:5
+ UINT8 Extension : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_RDIMM_REFERENCE_RAW_CARD;
+
+typedef union {
+ struct {
+ UINT8 RegisterCount : 2; ///< Bits 1:0
+ UINT8 DramRowCount : 2; ///< Bits 3:2
+ UINT8 : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_RDIMM_MODULE_ATTRIBUTES;
+
+typedef union {
+ struct {
+ UINT16 ContinuationCount : 7; ///< Bits 6:0
+ UINT16 ContinuationParity : 1; ///< Bits 7:7
+ UINT16 LastNonZeroByte : 8; ///< Bits 15:8
+ } Bits;
+ UINT16 Data;
+ UINT8 Data8[2];
+} SPD_MANUFACTURER_ID_CODE;
+
+typedef struct {
+ UINT8 Year; ///< Year represented in BCD (00h = 2000)
+ UINT8 Week; ///< Year represented in BCD (47h = week 47)
+} SPD_MANUFACTURING_DATE;
+
+typedef union {
+ UINT32 Data;
+ UINT16 SerialNumber16[2];
+ UINT8 SerialNumber8[4];
+} SPD_MANUFACTURER_SERIAL_NUMBER;
+
+typedef struct {
+ UINT8 Location; ///< Module Manufacturing Location
+} SPD_MANUFACTURING_LOCATION;
+
+typedef struct {
+ SPD_MANUFACTURER_ID_CODE IdCode; ///< Module Manufacturer ID Code
+ SPD_MANUFACTURING_LOCATION Location; ///< Module Manufacturing Location
+ SPD_MANUFACTURING_DATE Date; ///< Module Manufacturing Year, in BCD (range: 2000-2255)
+ SPD_MANUFACTURER_SERIAL_NUMBER SerialNumber; ///< Module Serial Number
+} SPD_UNIQUE_MODULE_ID;
+
+typedef union {
+ UINT16 Crc[1];
+ UINT8 Data8[2];
+} SPD_CYCLIC_REDUNDANCY_CODE;
+
+typedef union {
+ struct {
+ UINT8 ProfileEnable1 : 1; ///< Bits 0:0
+ UINT8 ProfileEnable2 : 1; ///< Bits 1:1
+ UINT8 ProfileConfig1 : 2; ///< Bits 3:2
+ UINT8 ProfileConfig2 : 2; ///< Bits 5:4
+ UINT8 : 2; ///< Bits 7:6
+ } Bits;
+ UINT8 Data;
+} SPD_XMP_ORG_CONFIG;
+
+typedef struct {
+ UINT16 XmpId; ///< 176-177 XMP Identification String
+ SPD_XMP_ORG_CONFIG XmpOrgConf; ///< 178 XMP Organization & Configuration
+ SPD_REVISION_STRUCT XmpRevision; ///< 179 XMP Revision
+ SPD_MEDIUM_TIMEBASE MediumTimeBase[MAX_XMP_PROFILES]; ///< 180-183 Medium Timebase (MTB)
+ SPD_FINE_TIMEBASE_STRUCT FineTimeBase; ///< 184 Fine Timebase (FTB) Dividend / Divisor
+} SPD_EXTREME_MEMORY_PROFILE_HEADER;
+
+typedef union {
+ struct {
+ UINT8 Decimal : 5;
+ UINT8 Integer : 2;
+ UINT8 : 1;
+ } Bits;
+ UINT8 Data;
+} SPD_VDD_VOLTAGE_LEVEL_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Decimal : 7;
+ UINT8 Integer : 1;
+ } Bits;
+ UINT8 Data;
+} SPD_VDD_VOLTAGE_LEVEL_STRUCT_2_0;
+
+typedef union {
+ struct {
+ UINT8 Fine : 2; ///< Bits 1:0
+ UINT8 Medium : 2; ///< Bits 3:2
+ UINT8 : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD4_TIMEBASE_STRUCT;
+
+typedef union {
+ struct {
+ UINT32 CL7 : 1; ///< Bits 0:0
+ UINT32 CL8 : 1; ///< Bits 1:1
+ UINT32 CL9 : 1; ///< Bits 2:2
+ UINT32 CL10 : 1; ///< Bits 3:3
+ UINT32 CL11 : 1; ///< Bits 4:4
+ UINT32 CL12 : 1; ///< Bits 5:5
+ UINT32 CL13 : 1; ///< Bits 6:6
+ UINT32 CL14 : 1; ///< Bits 7:7
+ UINT32 CL15 : 1; ///< Bits 8:8
+ UINT32 CL16 : 1; ///< Bits 9:9
+ UINT32 CL17 : 1; ///< Bits 10:10
+ UINT32 CL18 : 1; ///< Bits 11:11
+ UINT32 CL19 : 1; ///< Bits 12:12
+ UINT32 CL20 : 1; ///< Bits 13:13
+ UINT32 CL21 : 1; ///< Bits 14:14
+ UINT32 CL22 : 1; ///< Bits 15:15
+ UINT32 CL23 : 1; ///< Bits 16:16
+ UINT32 CL24 : 1; ///< Bits 17:17
+ UINT32 : 14; ///< Bits 31:18
+ } Bits;
+ UINT32 Data;
+ UINT16 Data16[2];
+ UINT8 Data8[4];
+} SPD4_CAS_LATENCIES_SUPPORTED_STRUCT;
+
+typedef struct {
+ SPD_VDD_VOLTAGE_LEVEL_STRUCT Vdd; ///< 185, 220 XMP Module VDD Voltage Level
+ SPD_TCK_MIN_MTB_STRUCT tCKmin; ///< 186, 221 XMP SDRAM Minimum Cycle Time (tCKmin)
+ SPD_TAA_MIN_MTB_STRUCT tAAmin; ///< 187, 222 XMP Minimum CAS Latency Time (tAAmin)
+ SPD_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 188-189, 223-224 XMP CAS Latencies Supported, Least Significant Byte
+ SPD_TCWL_MIN_MTB_STRUCT tCWLmin; ///< 190, 225 XMP Minimum CAS Write Latency Time (tCWLmin)
+ SPD_TRP_MIN_MTB_STRUCT tRPmin; ///< 191, 226 XMP Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 192, 227 XMP Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TWR_MIN_MTB_STRUCT tWRmin; ///< 193, 228 XMP Minimum Write Recovery Time (tWRmin)
+ SPD_TRAS_TRC_MIN_MTB_STRUCT tRASMintRCMinUpper; ///< 194, 229 XMP Upper Nibbles for tRAS and tRC
+ SPD_TRAS_MIN_MTB_STRUCT tRASmin; ///< 195, 230 XMP Minimum Active to Precharge Delay Time (tRASmin), Least Significant Byte
+ SPD_TRC_MIN_MTB_STRUCT tRCmin; ///< 196, 231 XMP Minimum Active to Active/Refresh Delay Time (tRCmin), Least Significant Byte
+ SPD_TREFI_MIN_MTB_STRUCT tREFImin; ///< 197-198, 232-233 XMP Maximum tREFI Time (Average Periodic Refresh Interval), Least Significant Byte
+ SPD_TRFC_MIN_MTB_STRUCT tRFCmin; ///< 199-200, 234-235 XMP Minimum Refresh Recovery Delay Time (tRFCmin), Least Significant Byte
+ SPD_TRTP_MIN_MTB_STRUCT tRTPmin; ///< 201, 236 XMP Minimum Internal Read to Precharge Command Delay Time (tRTPmin)
+ SPD_TRRD_MIN_MTB_STRUCT tRRDmin; ///< 202, 237 XMP Minimum Row Active to Row Active Delay Time (tRRDmin)
+ SPD_TFAW_MIN_MTB_UPPER_STRUCT tFAWMinUpper; ///< 203, 238 XMP Upper Nibble for tFAW
+ SPD_TFAW_MIN_MTB_STRUCT tFAWmin; ///< 204, 239 XMP Minimum Four Activate Window Delay Time (tFAWmin)
+ SPD_TWTR_MIN_MTB_STRUCT tWTRmin; ///< 205, 240 XMP Minimum Internal Write to Read Command Delay Time (tWTRmin)
+ UINT8 Reserved1[207 - 206 + 1]; ///< 206-207, 241-242 XMP Reserved
+ SPD_SYSTEM_COMMAND_RATE_STRUCT SystemCmdRate; ///< 208, 243 XMP System ADD/CMD Rate (1N or 2N mode)
+ SPD_AUTO_SELF_REFRESH_PERF_STRUCT AsrPerf; ///< 209, 244 XMP SDRAM Auto Self Refresh Performance (Sub 1x Refresh and IDD6 impact)
+ UINT8 VoltageLevel; ///< 210, 245 XMP Memory Controller Voltage Level
+ SPD_TCK_MIN_FTB_STRUCT tCKminFine; ///< 211, 246 XMP Fine Offset for SDRAM Minimum Cycle Time (tCKmin)
+ SPD_TAA_MIN_FTB_STRUCT tAAminFine; ///< 212, 247 XMP Fine Offset for Minimum CAS Latency Time (tAAmin)
+ SPD_TRP_MIN_FTB_STRUCT tRPminFine; ///< 213, 248 XMP Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 214, 249 XMP Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TRC_MIN_FTB_STRUCT tRCminFine; ///< 215, 250 XMP Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin)
+ UINT8 Reserved2[218 - 216 + 1]; ///< 216-218, 251-253 XMP Reserved
+ UINT8 VendorPersonality; ///< 219, 254 XMP Vendor Personality
+} SPD_EXTREME_MEMORY_PROFILE_DATA;
+
+typedef struct {
+ SPD_EXTREME_MEMORY_PROFILE_HEADER Header; ///< 176-184 XMP header
+ SPD_EXTREME_MEMORY_PROFILE_DATA Data[MAX_XMP_PROFILES]; ///< 185-254 XMP profiles
+} SPD_EXTREME_MEMORY_PROFILE;
+
+typedef struct {
+ UINT16 XmpId; ///< 384-385 XMP Identification String
+ SPD_XMP_ORG_CONFIG XmpOrgConf; ///< 386 XMP Organization & Configuration
+ SPD_REVISION_STRUCT XmpRevision; ///< 387 XMP Revision
+ SPD4_TIMEBASE_STRUCT TimeBase[MAX_XMP_PROFILES]; ///< 388-389 Medium and Fine Timebase
+ UINT8 Reserved[392 - 390 + 1]; ///< 390-392 Reserved
+} SPD_EXTREME_MEMORY_PROFILE_HEADER_2_0;
+
+typedef struct {
+ SPD_VDD_VOLTAGE_LEVEL_STRUCT_2_0 Vdd; ///< 393, 440 XMP Module VDD Voltage Level
+ UINT8 Reserved1[395 - 394 + 1]; ///< 394-395, 441-442 XMP Reserved
+ SPD_TCK_MIN_MTB_STRUCT tCKAVGmin; ///< 396, 443 XMP SDRAM Minimum Cycle Time (tCKAVGmin)
+ SPD4_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 397-400, 444-447 XMP CAS Latencies Supported
+ SPD_TAA_MIN_MTB_STRUCT tAAmin; ///< 401, 448 XMP Minimum CAS Latency Time (tAAmin)
+ SPD_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 402, 449 XMP Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TRP_MIN_MTB_STRUCT tRPmin; ///< 403, 450 XMP Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRAS_TRC_MIN_MTB_STRUCT tRASMintRCMinUpper; ///< 404, 451 XMP Upper Nibbles for tRAS and tRC
+ SPD_TRAS_MIN_MTB_STRUCT tRASmin; ///< 405, 452 XMP Minimum Active to Precharge Delay Time (tRASmin), Least Significant Byte
+ SPD_TRC_MIN_MTB_STRUCT tRCmin; ///< 406, 453 XMP Minimum Active to Active/Refresh Delay Time (tRCmin), Least Significant Byte
+ SPD_TRFC_MIN_MTB_STRUCT tRFC1min; ///< 407-408, 454-455 XMP Minimum Refresh Recovery Delay Time (tRFC1min)
+ SPD_TRFC_MIN_MTB_STRUCT tRFC2min; ///< 409-410, 456-457 XMP Minimum Refresh Recovery Delay Time (tRFC2min)
+ SPD_TRFC_MIN_MTB_STRUCT tRFC4min; ///< 411-412, 458-459 XMP Minimum Refresh Recovery Delay Time (tRFC4min)
+ SPD_TFAW_MIN_MTB_UPPER_STRUCT tFAWMinUpper; ///< 413, 460 Upper Nibble for tFAW
+ SPD_TFAW_MIN_MTB_STRUCT tFAWmin; ///< 414, 461 Minimum Four Activate Window Delay Time (tFAWmin)
+ SPD_TRRD_MIN_MTB_STRUCT tRRD_Smin; ///< 415, 462 Minimum Activate to Activate Delay Time (tRRD_Smin), different bank group
+ SPD_TRRD_MIN_MTB_STRUCT tRRD_Lmin; ///< 416, 463 Minimum Activate to Activate Delay Time (tRRD_Lmin), same bank group
+ UINT8 Reserved2[424 - 417 + 1]; ///< 417-424, 464-471 XMP Reserved
+ SPD_TRRD_MIN_FTB_STRUCT tRRD_LminFine; ///< 425, 472 Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Lmin), different bank group
+ SPD_TRRD_MIN_FTB_STRUCT tRRD_SminFine; ///< 426, 473 Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Smin), same bank group
+ SPD_TRC_MIN_FTB_STRUCT tRCminFine; ///< 427, 474 Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin)
+ SPD_TRP_MIN_FTB_STRUCT tRPminFine; ///< 428, 475 Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 429, 476 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TAA_MIN_FTB_STRUCT tAAminFine; ///< 430, 477 Fine Offset for Minimum CAS Latency Time (tAAmin)
+ SPD_TCK_MIN_FTB_STRUCT tCKAVGminFine; ///< 431, 478 Fine Offset for SDRAM Maximum Cycle Time (tCKAVGmin)
+ UINT8 Reserved3[439 - 432 + 1]; ///< 432-439, 479-486 XMP Reserved
+} SPD_EXTREME_MEMORY_PROFILE_DATA_2_0;
+
+typedef struct {
+ SPD_EXTREME_MEMORY_PROFILE_HEADER_2_0 Header; ///< 384-392 XMP header
+ SPD_EXTREME_MEMORY_PROFILE_DATA_2_0 Data[MAX_XMP_PROFILES]; ///< 393-486 XMP profiles
+} SPD_EXTREME_MEMORY_PROFILE_2_0;
+
+typedef struct {
+ SPD_DEVICE_DESCRIPTION_STRUCT Description; ///< 0 Number of Serial PD Bytes Written / SPD Device Size / CRC Coverage 1, 2
+ SPD_REVISION_STRUCT Revision; ///< 1 SPD Revision
+ SPD_DRAM_DEVICE_TYPE_STRUCT DramDeviceType; ///< 2 DRAM Device Type
+ SPD_MODULE_TYPE_STRUCT ModuleType; ///< 3 Module Type
+ SPD_SDRAM_DENSITY_BANKS_STRUCT SdramDensityAndBanks; ///< 4 SDRAM Density and Banks
+ SPD_SDRAM_ADDRESSING_STRUCT SdramAddressing; ///< 5 SDRAM Addressing
+ SPD_MODULE_NOMINAL_VOLTAGE_STRUCT ModuleNominalVoltage; ///< 6 Module Nominal Voltage, VDD
+ SPD_MODULE_ORGANIZATION_STRUCT ModuleOrganization; ///< 7 Module Organization
+ SPD_MODULE_MEMORY_BUS_WIDTH_STRUCT ModuleMemoryBusWidth; ///< 8 Module Memory Bus Width
+ SPD_FINE_TIMEBASE_STRUCT FineTimebase; ///< 9 Fine Timebase (FTB) Dividend / Divisor
+ SPD_MEDIUM_TIMEBASE MediumTimebase; ///< 10-11 Medium Timebase (MTB) Dividend
+ SPD_TCK_MIN_MTB_STRUCT tCKmin; ///< 12 SDRAM Minimum Cycle Time (tCKmin)
+ UINT8 Reserved1; ///< 13 Reserved
+ SPD_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 14-15 CAS Latencies Supported
+ SPD_TAA_MIN_MTB_STRUCT tAAmin; ///< 16 Minimum CAS Latency Time (tAAmin)
+ SPD_TWR_MIN_MTB_STRUCT tWRmin; ///< 17 Minimum Write Recovery Time (tWRmin)
+ SPD_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 18 Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TRRD_MIN_MTB_STRUCT tRRDmin; ///< 19 Minimum Row Active to Row Active Delay Time (tRRDmin)
+ SPD_TRP_MIN_MTB_STRUCT tRPmin; ///< 20 Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRAS_TRC_MIN_MTB_STRUCT tRASMintRCMinUpper; ///< 21 Upper Nibbles for tRAS and tRC
+ SPD_TRAS_MIN_MTB_STRUCT tRASmin; ///< 22 Minimum Active to Precharge Delay Time (tRASmin), Least Significant Byte
+ SPD_TRC_MIN_MTB_STRUCT tRCmin; ///< 23 Minimum Active to Active/Refresh Delay Time (tRCmin), Least Significant Byte
+ SPD_TRFC_MIN_MTB_STRUCT tRFCmin; ///< 24-25 Minimum Refresh Recovery Delay Time (tRFCmin)
+ SPD_TWTR_MIN_MTB_STRUCT tWTRmin; ///< 26 Minimum Internal Write to Read Command Delay Time (tWTRmin)
+ SPD_TRTP_MIN_MTB_STRUCT tRTPmin; ///< 27 Minimum Internal Read to Precharge Command Delay Time (tRTPmin)
+ SPD_TFAW_MIN_MTB_UPPER_STRUCT tFAWMinUpper; ///< 28 Upper Nibble for tFAW
+ SPD_TFAW_MIN_MTB_STRUCT tFAWmin; ///< 29 Minimum Four Activate Window Delay Time (tFAWmin)
+ SPD_SDRAM_OPTIONAL_FEATURES_STRUCT SdramOptionalFeatures; ///< 30 SDRAM Optional Features
+ SPD_SDRAM_THERMAL_REFRESH_STRUCT ThermalAndRefreshOptions; ///< 31 SDRAMThermalAndRefreshOptions
+ SPD_MODULE_THERMAL_SENSOR_STRUCT ModuleThermalSensor; ///< 32 Module Thermal Sensor
+ SPD_SDRAM_DEVICE_TYPE_STRUCT SdramDeviceType; ///< 33 SDRAM Device Type
+ SPD_TCK_MIN_FTB_STRUCT tCKminFine; ///< 34 Fine Offset for SDRAM Minimum Cycle Time (tCKmin)
+ SPD_TAA_MIN_FTB_STRUCT tAAminFine; ///< 35 Fine Offset for Minimum CAS Latency Time (tAAmin)
+ SPD_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 36 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TRP_MIN_FTB_STRUCT tRPminFine; ///< 37 Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRC_MIN_FTB_STRUCT tRCminFine; ///< 38 Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin)
+ SPD_TRP_AB_MTB_STRUCT tRPab; ///< 39 Minimum Row Precharge Delay Time for all banks (tRPab)
+ SPD_TRP_AB_FTB_STRUCT tRPabFine; ///< 40 Fine Offset for Minimum Row Precharge Delay Time for all banks (tRPab)
+ SPD_PTRR_SUPPORT_STRUCT pTRRsupport; ///< 41 - pTRR support with TMAC value
+ UINT8 Reserved3[59 - 42 + 1]; ///< 42 - 59 Reserved
+} SPD_GENERAL_SECTION;
+
+typedef struct {
+ SPD_UNBUF_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 60 Module Nominal Height
+ SPD_UNBUF_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 61 Module Maximum Thickness
+ SPD_UNBUF_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 62 Reference Raw Card Used
+ SPD_UNBUF_ADDRESS_MAPPING AddressMappingEdgeConn; ///< 63 Address Mapping from Edge Connector to DRAM
+ UINT8 Reserved[116 - 64 + 1]; ///< 64-116 Reserved
+} SPD_MODULE_UNBUFFERED;
+
+typedef struct {
+ SPD_RDIMM_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 60 Module Nominal Height
+ SPD_RDIMM_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 61 Module Maximum Thickness
+ SPD_RDIMM_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 62 Reference Raw Card Used
+ SPD_RDIMM_MODULE_ATTRIBUTES DimmModuleAttributes; ///< 63 DIMM Module Attributes
+ UINT8 Reserved[116 - 64 + 1]; ///< 64-116 Reserved
+} SPD_MODULE_REGISTERED;
+
+typedef union {
+ SPD_MODULE_UNBUFFERED Unbuffered;
+ SPD_MODULE_REGISTERED Registered;
+} SPD_MODULE_SPECIFIC;
+
+typedef struct {
+ UINT8 ModulePartNumber[145 - 128 + 1]; ///< 128-145 Module Part Number
+} SPD_MODULE_PART_NUMBER;
+
+typedef struct {
+ UINT8 ModuleRevisionCode[147 - 146 + 1]; ///< 146-147 Module Revision Code
+} SPD_MODULE_REVISION_CODE;
+
+typedef struct {
+ UINT8 ManufactureSpecificData[175 - 150 + 1]; ///< 150-175 Manufacturer's Specific Data
+} SPD_MANUFACTURE_SPECIFIC;
+
+///
+/// DDR3 Serial Presence Detect structure
+///
+typedef struct {
+ SPD_GENERAL_SECTION General; ///< 0-59 General Section
+ SPD_MODULE_SPECIFIC Module; ///< 60-116 Module-Specific Section
+ SPD_UNIQUE_MODULE_ID ModuleId; ///< 117-125 Unique Module ID
+ SPD_CYCLIC_REDUNDANCY_CODE Crc; ///< 126-127 Cyclical Redundancy Code (CRC)
+ SPD_MODULE_PART_NUMBER ModulePartNumber; ///< 128-145 Module Part Number
+ SPD_MODULE_REVISION_CODE ModuleRevisionCode; ///< 146-147 Module Revision Code
+ SPD_MANUFACTURER_ID_CODE DramIdCode; ///< 148-149 Dram Manufacturer ID Code
+ SPD_MANUFACTURE_SPECIFIC ManufactureSpecificData; ///< 150-175 Manufacturer's Specific Data
+ SPD_EXTREME_MEMORY_PROFILE Xmp; ///< 176-254 Intel(r) Extreme Memory Profile support
+ UINT8 Reserved; ///< 255 Reserved
+} MrcSpdDdr3;
+
+typedef union {
+ struct {
+ UINT8 Density : 4; ///< Bits 3:0
+ UINT8 BankAddress : 2; ///< Bits 5:4
+ UINT8 BankGroup : 2; ///< Bits 7:6
+ } Bits;
+ UINT8 Data;
+} SPD4_SDRAM_DENSITY_BANKS_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 SignalLoading : 2; ///< Bits 1:0
+ UINT8 : 2; ///< Bits 3:2
+ UINT8 DieCount : 3; ///< Bits 6:4
+ UINT8 SdramDeviceType : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD4_SDRAM_DEVICE_TYPE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 OperationAt1_20 : 1; ///< Bits 0:0
+ UINT8 EndurantAt1_20 : 1; ///< Bits 1:1
+ UINT8 : 6; ///< Bits 7:2
+ } Bits;
+ UINT8 Data;
+} SPD4_MODULE_NOMINAL_VOLTAGE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tCKmax : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD4_TCK_MAX_MTB_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tCKmaxFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD4_TCK_MAX_FTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD4_SDRAM_THERMAL_REFRESH_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Height : 5; ///< Bits 4:0
+ UINT8 RawCardExtension : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD4_UNBUF_MODULE_NOMINAL_HEIGHT;
+
+typedef union {
+ struct {
+ UINT8 Height : 5; ///< Bits 4:0
+ UINT8 RawCardExtension : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD4_RDIMM_MODULE_NOMINAL_HEIGHT;
+
+typedef struct {
+ SPD_DEVICE_DESCRIPTION_STRUCT Description; ///< 0 Number of Serial PD Bytes Written / SPD Device Size / CRC Coverage 1, 2
+ SPD_REVISION_STRUCT Revision; ///< 1 SPD Revision
+ SPD_DRAM_DEVICE_TYPE_STRUCT DramDeviceType; ///< 2 DRAM Device Type
+ SPD_MODULE_TYPE_STRUCT ModuleType; ///< 3 Module Type
+ SPD4_SDRAM_DENSITY_BANKS_STRUCT SdramDensityAndBanks; ///< 4 SDRAM Density and Banks
+ SPD_SDRAM_ADDRESSING_STRUCT SdramAddressing; ///< 5 SDRAM Addressing
+ SPD4_SDRAM_DEVICE_TYPE_STRUCT SdramDeviceType; ///< 6 SDRAM Device Type
+ SPD_PTRR_SUPPORT_STRUCT pTRRsupport; ///< 7 pTRR support with TMAC value
+ SPD4_SDRAM_THERMAL_REFRESH_STRUCT ThermalAndRefreshOptions; ///< 8 SDRAM Thermal and Refresh Options
+ UINT8 Reserved0[10 - 9 + 1]; ///< 9-10 Reserved
+ SPD4_MODULE_NOMINAL_VOLTAGE_STRUCT ModuleNominalVoltage; ///< 11 Module Nominal Voltage, VDD
+ SPD_MODULE_ORGANIZATION_STRUCT ModuleOrganization; ///< 12 Module Organization
+ SPD_MODULE_MEMORY_BUS_WIDTH_STRUCT ModuleMemoryBusWidth; ///< 13 Module Memory Bus Width
+ SPD_MODULE_THERMAL_SENSOR_STRUCT ModuleThermalSensor; ///< 14 Module Thermal Sensor
+ UINT8 Reserved1[16 - 15 + 1]; ///< 15-16 Reserved
+ SPD4_TIMEBASE_STRUCT Timebase; ///< 17 Timebases
+ SPD_TCK_MIN_MTB_STRUCT tCKmin; ///< 18 SDRAM Minimum Cycle Time (tCKmin)
+ SPD4_TCK_MAX_MTB_STRUCT tCKmax; ///< 19 SDRAM Maximum Cycle Time (tCKmax)
+ SPD4_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 20-23 CAS Latencies Supported
+ SPD_TAA_MIN_MTB_STRUCT tAAmin; ///< 24 Minimum CAS Latency Time (tAAmin)
+ SPD_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 25 Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TRP_MIN_MTB_STRUCT tRPmin; ///< 26 Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRAS_TRC_MIN_MTB_STRUCT tRASMintRCMinUpper; ///< 27 Upper Nibbles for tRAS and tRC
+ SPD_TRAS_MIN_MTB_STRUCT tRASmin; ///< 28 Minimum Active to Precharge Delay Time (tRASmin), Least Significant Byte
+ SPD_TRC_MIN_MTB_STRUCT tRCmin; ///< 29 Minimum Active to Active/Refresh Delay Time (tRCmin), Least Significant Byte
+ SPD_TRFC_MIN_MTB_STRUCT tRFC1min; ///< 30-31 Minimum Refresh Recovery Delay Time (tRFC1min)
+ SPD_TRFC_MIN_MTB_STRUCT tRFC2min; ///< 32-33 Minimum Refresh Recovery Delay Time (tRFC2min)
+ SPD_TRFC_MIN_MTB_STRUCT tRFC4min; ///< 34-35 Minimum Refresh Recovery Delay Time (tRFC4min)
+ SPD_TFAW_MIN_MTB_UPPER_STRUCT tFAWMinUpper; ///< 36 Upper Nibble for tFAW
+ SPD_TFAW_MIN_MTB_STRUCT tFAWmin; ///< 37 Minimum Four Activate Window Delay Time (tFAWmin)
+ SPD_TRRD_MIN_MTB_STRUCT tRRD_Smin; ///< 38 Minimum Activate to Activate Delay Time (tRRD_Smin), different bank group
+ SPD_TRRD_MIN_MTB_STRUCT tRRD_Lmin; ///< 39 Minimum Activate to Activate Delay Time (tRRD_Lmin), same bank group
+ UINT8 Reserved2[117 - 40 + 1]; ///< 40-117 Reserved
+ SPD_TRRD_MIN_FTB_STRUCT tRRD_LminFine; ///< 118 Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Lmin), different bank group
+ SPD_TRRD_MIN_FTB_STRUCT tRRD_SminFine; ///< 119 Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Smin), same bank group
+ SPD_TRC_MIN_FTB_STRUCT tRCminFine; ///< 120 Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin)
+ SPD_TRP_MIN_FTB_STRUCT tRPminFine; ///< 121 Minimum Row Precharge Delay Time (tRPmin)
+ SPD_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 122 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TAA_MIN_FTB_STRUCT tAAminFine; ///< 123 Fine Offset for Minimum CAS Latency Time (tAAmin)
+ SPD4_TCK_MAX_FTB_STRUCT tCKmaxFine; ///< 124 Fine Offset for SDRAM Minimum Cycle Time (tCKmax)
+ SPD_TCK_MIN_FTB_STRUCT tCKminFine; ///< 125 Fine Offset for SDRAM Maximum Cycle Time (tCKmin)
+ SPD_CYCLIC_REDUNDANCY_CODE Crc; ///< 126-127 Cyclical Redundancy Code (CRC)
+} SPD4_BASE_SECTION;
+
+typedef struct {
+ SPD4_UNBUF_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 128 Module Nominal Height
+ SPD_UNBUF_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 129 Module Maximum Thickness
+ SPD_UNBUF_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 130 Reference Raw Card Used
+ SPD_UNBUF_ADDRESS_MAPPING AddressMappingEdgeConn; ///< 131 Address Mapping from Edge Connector to DRAM
+ UINT8 Reserved[253 - 132 + 1]; ///< 132-253 Reserved
+ SPD_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC)
+} SPD4_MODULE_UNBUFFERED;
+
+typedef struct {
+ SPD4_RDIMM_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 128 Module Nominal Height
+ SPD_RDIMM_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 129 Module Maximum Thickness
+ SPD_RDIMM_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 130 Reference Raw Card Used
+ SPD_RDIMM_MODULE_ATTRIBUTES DimmModuleAttributes; ///< 131 DIMM Module Attributes
+ UINT8 Reserved[253 - 132 + 1]; ///< 253-132 Reserved
+ SPD_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC)
+} SPD4_MODULE_REGISTERED;
+
+typedef union {
+ SPD4_MODULE_UNBUFFERED Unbuffered; ///< 128-255 Unbuffered Memory Module Types
+ SPD4_MODULE_REGISTERED Registered; ///< 128-255 Registered Memory Module Types
+} SPD4_MODULE_SPECIFIC;
+
+typedef struct {
+ UINT8 ModulePartNumber[348 - 329 + 1]; ///< 329-348 Module Part Number
+} SPD4_MODULE_PART_NUMBER;
+
+typedef struct {
+ UINT8 ManufactureSpecificData[381 - 353 + 1]; ///< 353-381 Manufacturer's Specific Data
+} SPD4_MANUFACTURE_SPECIFIC;
+
+typedef UINT8 SPD4_MODULE_REVISION_CODE;///< 349 Module Revision Code
+typedef UINT8 SPD4_DRAM_STEPPING; ///< 352 Dram Stepping
+
+typedef struct {
+ SPD_UNIQUE_MODULE_ID ModuleId; ///< 320-328 Unique Module ID
+ SPD4_MODULE_PART_NUMBER ModulePartNumber; ///< 329-348 Module Part Number
+ SPD4_MODULE_REVISION_CODE ModuleRevisionCode; ///< 349 Module Revision Code
+ SPD_MANUFACTURER_ID_CODE DramIdCode; ///< 350-351 Dram Manufacturer ID Code
+ SPD4_DRAM_STEPPING DramStepping; ///< 352 Dram Stepping
+ SPD4_MANUFACTURE_SPECIFIC ManufactureSpecificData; ///< 353-381 Manufacturer's Specific Data
+ SPD_CYCLIC_REDUNDANCY_CODE Crc; ///< 382-383 Cyclical Redundancy Code (CRC)
+} SPD4_MANUFACTURING_DATA;
+
+typedef union {
+ SPD_EXTREME_MEMORY_PROFILE_2_0 Xmp; ///< 384-463 Intel(r) Extreme Memory Profile support
+ UINT8 Reserved0[511 - 384 + 1]; ///< 384-511 Unbuffered Memory Module Types
+} SPD4_END_USER_SECTION;
+
+///
+/// DDR4 Serial Presence Detect structure
+///
+typedef struct {
+ SPD4_BASE_SECTION Base; ///< 0-127 Base Configuration and DRAM Parameters
+ SPD4_MODULE_SPECIFIC Module; ///< 128-255 Module-Specific Section
+ UINT8 Reserved0[319 - 256 + 1]; ///< 256-319 Reserved
+ SPD4_MANUFACTURING_DATA ManufactureInfo; ///< 320-383 Manufacturing Information
+ SPD4_END_USER_SECTION EndUser; ///< 384-511 End User Programmable
+} MrcSpdDdr4;
+
+typedef union {
+ struct {
+ UINT8 Fine : 2; ///< Bits 1:0
+ UINT8 Medium : 2; ///< Bits 3:2
+ UINT8 : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_TIMEBASE_STRUCT;
+
+typedef union {
+ struct {
+ UINT32 CL3 : 1; ///< Bits 0:0
+ UINT32 CL6 : 1; ///< Bits 1:1
+ UINT32 CL8 : 1; ///< Bits 2:2
+ UINT32 CL9 : 1; ///< Bits 3:3
+ UINT32 CL10 : 1; ///< Bits 4:4
+ UINT32 CL11 : 1; ///< Bits 5:5
+ UINT32 CL12 : 1; ///< Bits 6:6
+ UINT32 CL14 : 1; ///< Bits 7:7
+ UINT32 CL16 : 1; ///< Bits 8:8
+ UINT32 : 1; ///< Bits 9:9
+ UINT32 CL20 : 1; ///< Bits 10:10
+ UINT32 CL22 : 1; ///< Bits 11:11
+ UINT32 CL24 : 1; ///< Bits 12:12
+ UINT32 : 1; ///< Bits 13:13
+ UINT32 CL28 : 1; ///< Bits 14:14
+ UINT32 : 1; ///< Bits 15:15
+ UINT32 CL32 : 1; ///< Bits 16:16
+ UINT32 : 1; ///< Bits 17:17
+ UINT32 CL36 : 1; ///< Bits 18:18
+ UINT32 : 1; ///< Bits 19:19
+ UINT32 CL40 : 1; ///< Bits 20:20
+ UINT32 : 11; ///< Bits 31:21
+ } Bits;
+ UINT32 Data;
+ UINT16 Data16[2];
+ UINT8 Data8[4];
+} SPD_LPDDR_CAS_LATENCIES_SUPPORTED_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Density : 4; ///< Bits 3:0
+ UINT8 BankAddress : 2; ///< Bits 5:4
+ UINT8 BankGroup : 2; ///< Bits 7:6
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_SDRAM_DENSITY_BANKS_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 SignalLoading : 2; ///< Bits 1:0
+ UINT8 ChannelsPerDie : 2; ///< Bits 3:2
+ UINT8 DieCount : 3; ///< Bits 6:4
+ UINT8 SdramPackageType : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_SDRAM_PACKAGE_TYPE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 OperationAt1_20 : 1; ///< Bits 0:0
+ UINT8 EndurantAt1_20 : 1; ///< Bits 1:1
+ UINT8 OperationAt1_10 : 1; ///< Bits 2:2
+ UINT8 EndurantAt1_10 : 1; ///< Bits 3:3
+ UINT8 OperationAtTBD2V : 1; ///< Bits 4:4
+ UINT8 EndurantAtTBD2V : 1; ///< Bits 5:5
+ UINT8 : 2; ///< Bits 7:6
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_MODULE_NOMINAL_VOLTAGE_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 tCKmax : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_TCK_MAX_MTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 ReadLatencyMode : 2; ///< Bits 1:0
+ UINT8 WriteLatencySet : 2; ///< Bits 3:2
+ UINT8 : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_RW_LATENCY_OPTION_STRUCT;
+
+typedef union {
+ struct {
+ INT8 tCKmaxFine : 8; ///< Bits 7:0
+ } Bits;
+ INT8 Data;
+} SPD_LPDDR_TCK_MAX_FTB_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 : 8; ///< Bits 7:0
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_SDRAM_THERMAL_REFRESH_STRUCT;
+
+typedef union {
+ struct {
+ UINT8 Height : 5; ///< Bits 4:0
+ UINT8 RawCardExtension : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_UNBUF_MODULE_NOMINAL_HEIGHT;
+
+typedef union {
+ struct {
+ UINT8 Height : 5; ///< Bits 4:0
+ UINT8 RawCardExtension : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_RDIMM_MODULE_NOMINAL_HEIGHT;
+
+typedef struct {
+ SPD_DEVICE_DESCRIPTION_STRUCT Description; ///< 0 Number of Serial PD Bytes Written / SPD Device Size / CRC Coverage 1, 2
+ SPD_REVISION_STRUCT Revision; ///< 1 SPD Revision
+ SPD_DRAM_DEVICE_TYPE_STRUCT DramDeviceType; ///< 2 DRAM Device Type
+ SPD_MODULE_TYPE_STRUCT ModuleType; ///< 3 Module Type
+ SPD_LPDDR_SDRAM_DENSITY_BANKS_STRUCT SdramDensityAndBanks; ///< 4 SDRAM Density and Banks
+ SPD_SDRAM_ADDRESSING_STRUCT SdramAddressing; ///< 5 SDRAM Addressing
+ SPD_LPDDR_SDRAM_PACKAGE_TYPE_STRUCT SdramPackageType; ///< 6 SDRAM Package Type
+ SPD_PTRR_SUPPORT_STRUCT pTRRsupport; ///< 7 pTRR support with TMAC value - SDRAM Optional Features
+ SPD_LPDDR_SDRAM_THERMAL_REFRESH_STRUCT ThermalAndRefreshOptions; ///< 8 SDRAM Thermal and Refresh Options
+ UINT8 Reserved0[10 - 9 + 1]; ///< 9-10 Reserved
+ SPD_LPDDR_MODULE_NOMINAL_VOLTAGE_STRUCT ModuleNominalVoltage; ///< 11 Module Nominal Voltage, VDD
+ SPD_MODULE_ORGANIZATION_STRUCT ModuleOrganization; ///< 12 Module Organization
+ SPD_MODULE_MEMORY_BUS_WIDTH_STRUCT ModuleMemoryBusWidth; ///< 13 Module Memory Bus Width
+ SPD_MODULE_THERMAL_SENSOR_STRUCT ModuleThermalSensor; ///< 14 Module Thermal Sensor
+ UINT8 Reserved1[16 - 15 + 1]; ///< 15-16 Reserved
+ SPD_LPDDR_TIMEBASE_STRUCT Timebase; ///< 17 Timebases
+ SPD_TCK_MIN_MTB_STRUCT tCKmin; ///< 18 SDRAM Minimum Cycle Time (tCKmin)
+ SPD_LPDDR_TCK_MAX_MTB_STRUCT tCKmax; ///< 19 SDRAM Maximum Cycle Time (tCKmax)
+ SPD_LPDDR_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 20-23 CAS Latencies Supported
+ SPD_TAA_MIN_MTB_STRUCT tAAmin; ///< 24 Minimum CAS Latency Time (tAAmin)
+ SPD_LPDDR_RW_LATENCY_OPTION_STRUCT LatencySetOptions; ///< 25 Read and Write Latency Set Options
+ SPD_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 26 Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TRP_AB_MTB_STRUCT tRPab; ///< 27 Minimum Row Precharge Delay Time (tRPab), all banks
+ SPD_TRP_PB_MTB_STRUCT tRPpb; ///< 28 Minimum Row Precharge Delay Time (tRPpb), per bank
+ SPD_TRFC_AB_MTB_STRUCT tRFCab; ///< 29-30 Minimum Refresh Recovery Delay Time (tRFCab), all banks
+ SPD_TRFC_PB_MTB_STRUCT tRFCpb; ///< 31-32 Minimum Refresh Recovery Delay Time (tRFCpb), per bank
+ UINT8 Reserved2[119 - 33 + 1]; ///< 33-119 Reserved
+ SPD_TRP_PB_FTB_STRUCT tRPpbFine; ///< 120 Fine Offset for Minimum Row Precharge Delay Time (tRPpbFine), per bank
+ SPD_TRP_AB_FTB_STRUCT tRPabFine; ///< 121 Fine Offset for Minimum Row Precharge Delay Time (tRPabFine), all ranks
+ SPD_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 122 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin)
+ SPD_TAA_MIN_FTB_STRUCT tAAminFine; ///< 123 Fine Offset for Minimum CAS Latency Time (tAAmin)
+ SPD_LPDDR_TCK_MAX_FTB_STRUCT tCKmaxFine; ///< 124 Fine Offset for SDRAM Maximum Cycle Time (tCKmax)
+ SPD_TCK_MIN_FTB_STRUCT tCKminFine; ///< 125 Fine Offset for SDRAM Minimum Cycle Time (tCKmin)
+ SPD_CYCLIC_REDUNDANCY_CODE Crc; ///< 126-127 Cyclical Redundancy Code (CRC)
+} SPD_LPDDR_BASE_SECTION;
+
+typedef union {
+ struct {
+ UINT8 FrontThickness : 4; ///< Bits 3:0
+ UINT8 BackThickness : 4; ///< Bits 7:4
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_MODULE_MAXIMUM_THICKNESS;
+
+typedef union {
+ struct {
+ UINT8 Height : 5; ///< Bits 4:0
+ UINT8 RawCardExtension : 3; ///< Bits 7:5
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_MODULE_NOMINAL_HEIGHT;
+
+typedef union {
+ struct {
+ UINT8 Card : 5; ///< Bits 4:0
+ UINT8 Revision : 2; ///< Bits 6:5
+ UINT8 Extension : 1; ///< Bits 7:7
+ } Bits;
+ UINT8 Data;
+} SPD_LPDDR_REFERENCE_RAW_CARD;
+
+typedef struct {
+ SPD_LPDDR_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 128 Module Nominal Height
+ SPD_LPDDR_MODULE_MAXIMUM_THICKNESS ModuleMaximumThickness; ///< 129 Module Maximum Thickness
+ SPD_LPDDR_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 130 Reference Raw Card Used
+ UINT8 Reserved[253 - 131 + 1]; ///< 131-253 Reserved
+ SPD_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC)
+} SPD_LPDDR_MODULE_LPDIMM;
+
+typedef union {
+ SPD_LPDDR_MODULE_LPDIMM LpDimm; ///< 128-255 Unbuffered Memory Module Types
+} SPD_LPDDR_MODULE_SPECIFIC;
+
+typedef struct {
+ UINT8 ModulePartNumber[348 - 329 + 1]; ///< 329-348 Module Part Number
+} SPD_LPDDR_MODULE_PART_NUMBER;
+
+typedef struct {
+ UINT8 ManufactureSpecificData[381 - 353 + 1]; ///< 353-381 Manufacturer's Specific Data
+} SPD_LPDDR_MANUFACTURE_SPECIFIC;
+
+typedef UINT8 SPD_LPDDR_MODULE_REVISION_CODE;///< 349 Module Revision Code
+typedef UINT8 SPD_LPDDR_DRAM_STEPPING; ///< 352 Dram Stepping
+
+typedef struct {
+ SPD_UNIQUE_MODULE_ID ModuleId; ///< 320-328 Unique Module ID
+ SPD_LPDDR_MODULE_PART_NUMBER ModulePartNumber; ///< 329-348 Module Part Number
+ SPD_LPDDR_MODULE_REVISION_CODE ModuleRevisionCode; ///< 349 Module Revision Code
+ SPD_MANUFACTURER_ID_CODE DramIdCode; ///< 350-351 Dram Manufacturer ID Code
+ SPD_LPDDR_DRAM_STEPPING DramStepping; ///< 352 Dram Stepping
+ SPD_LPDDR_MANUFACTURE_SPECIFIC ManufactureSpecificData; ///< 353-381 Manufacturer's Specific Data
+ UINT8 Reserved[383 - 382 + 1]; ///< 382-383 Reserved
+} SPD_LPDDR_MANUFACTURING_DATA;
+
+typedef union {
+ UINT8 Reserved0[511 - 384 + 1]; ///< 384-511 End User Programmable
+} SPD_LPDDR_END_USER_SECTION;
+
+typedef struct {
+ SPD_LPDDR_BASE_SECTION Base; ///< 0-127 Base Configuration and DRAM Parameters
+ SPD_LPDDR_MODULE_SPECIFIC Module; ///< 128-255 Module-Specific Section
+ UINT8 Reserved0[319 - 256 + 1]; ///< 256-319 Reserved
+ SPD_LPDDR_MANUFACTURING_DATA ManufactureInfo; ///< 320-383 Manufacturing Information
+ SPD_LPDDR_END_USER_SECTION EndUser; ///< 384-511 End User Programmable
+} MrcSpdLpDdr;
+
+typedef union {
+ MrcSpdDdr3 Ddr3;
+ MrcSpdDdr4 Ddr4;
+ MrcSpdLpDdr Lpddr;
+} MrcSpd;
+
+#ifndef MAX_SPD_SAVE
+#define MAX_SPD_SAVE (sizeof (SPD_MANUFACTURER_ID_CODE) + \
+ sizeof (SPD_MANUFACTURING_LOCATION) + \
+ sizeof (SPD_MANUFACTURING_DATE) + \
+ sizeof (SPD_MANUFACTURER_SERIAL_NUMBER) + \
+ sizeof (SPD4_MODULE_PART_NUMBER))
+#endif
+
+#pragma pack (pop)
+#endif // _MrcSpdData_h_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcTypes.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcTypes.h
new file mode 100644
index 0000000000..5bb771089d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/MemoryInit/Include/MrcTypes.h
@@ -0,0 +1,237 @@
+/** @file
+
+ Include the the general MRC types
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _MRC_TYPES_H
+#define _MRC_TYPES_H
+
+#ifdef MRC_MINIBIOS_BUILD
+#include "MrcMiniBiosEfiDefs.h"
+#else
+#include <Base.h>
+#endif // MRC_MINIBIOS_BUILD
+
+//
+// Data Types
+//
+typedef union {
+ struct {
+ UINT32 Low;
+ UINT32 High;
+ } Data32;
+ UINT64 Data;
+} UINT64_STRUCT;
+
+typedef union {
+ struct {
+ INT32 Low;
+ INT32 High;
+ } Data32;
+ INT64 Data;
+} INT64_STRUCT;
+
+#define UNSUPPORT 0
+#define SUPPORT 1
+
+typedef enum {
+ mrcSuccess,
+ mrcFail,
+ mrcWrongInputParameter,
+ mrcCasError,
+ mrcTimingError,
+ mrcSenseAmpErr,
+ mrcReadMPRErr,
+ mrcReadLevelingError,
+ mrcWriteLevelingError,
+ mrcDataTimeCentering1DErr,
+ mrcWriteVoltage2DError,
+ mrcReadVoltage2DError,
+ mrcMiscTrainingError,
+ mrcWrError,
+ mrcDimmNotSupport,
+ mrcChannelNotSupport,
+ mrcPiSettingError,
+ mrcDqsPiSettingError,
+ mrcDeviceBusy,
+ mrcFrequencyChange,
+ mrcReutSequenceError,
+ mrcCrcError,
+ mrcFrequencyError,
+ mrcDimmNotExist,
+ mrcColdBootRequired,
+ mrcRoundTripLatencyError,
+ mrcMixedDimmSystem,
+ mrcAliasDetected,
+ mrcRetrain,
+ mrcRtpError,
+ mrcUnsupportedTechnology,
+ mrcMappingError,
+ mrcSocketNotSupported,
+ mrcControllerNotSupported,
+ mrcRankNotSupported,
+ mrcTurnAroundTripError
+} MrcStatus;
+
+//
+// general macros
+//
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef ABS
+#define ABS(x) (((x) < 0) ? (-(x)) : (x))
+#endif
+
+//
+// Make sure x is inside the range of [a..b]
+//
+#ifndef RANGE
+#define RANGE(x, a, b) (MIN ((b), MAX ((x), (a))))
+#endif
+
+#ifndef DIVIDECEIL
+#define DIVIDECEIL(a, b) (((a) + (b) - 1) / (b))
+#endif
+
+#ifndef DIVIDEROUND
+#define DIVIDEROUND(a, b) (((a) * (b) > 0) ? ((a) + (b) / 2) / (b) : ((a) - (b) / 2) / (b))
+#endif
+
+#ifndef DIVIDEFLOOR
+#define DIVIDEFLOOR(a, b) ((a) / (b))
+#endif
+
+//
+// Number of elements in a 1D array
+//
+#ifndef ARRAY_COUNT
+#define ARRAY_COUNT(a) (sizeof (a) / sizeof (a[0]))
+#endif
+
+//
+// use for ignore parames
+//
+// #define MRC_IGNORE_PARAM(x) ((x) = (x))
+//
+#if _MSC_EXTENSIONS
+//
+// Disable warning that make it impossible to compile at /W4
+// This only works for Microsoft* tools
+//
+//
+// Disabling bitfield type checking warnings.
+//
+#pragma warning (disable : 4214)
+//
+// Unreferenced formal parameter - We are object oriented, so we pass parameters even
+// if we don't need them.
+//
+#pragma warning (disable : 4100)
+//
+// ASSERT(FALSE) or while (TRUE) are legal constructs so supress this warning
+//
+#pragma warning(disable : 4127)
+//
+// The given function was selected for inline expansion, but the compiler did not perform the inlining.
+//
+#pragma warning(disable : 4710)
+
+#endif // _MSC_EXTENSIONS
+#define MRC_BIT0 0x00000001
+#define MRC_BIT1 0x00000002
+#define MRC_BIT2 0x00000004
+#define MRC_BIT3 0x00000008
+#define MRC_BIT4 0x00000010
+#define MRC_BIT5 0x00000020
+#define MRC_BIT6 0x00000040
+#define MRC_BIT7 0x00000080
+#define MRC_BIT8 0x00000100
+#define MRC_BIT9 0x00000200
+#define MRC_BIT10 0x00000400
+#define MRC_BIT11 0x00000800
+#define MRC_BIT12 0x00001000
+#define MRC_BIT13 0x00002000
+#define MRC_BIT14 0x00004000
+#define MRC_BIT15 0x00008000
+#define MRC_BIT16 0x00010000
+#define MRC_BIT17 0x00020000
+#define MRC_BIT18 0x00040000
+#define MRC_BIT19 0x00080000
+#define MRC_BIT20 0x00100000
+#define MRC_BIT21 0x00200000
+#define MRC_BIT22 0x00400000
+#define MRC_BIT23 0x00800000
+#define MRC_BIT24 0x01000000
+#define MRC_BIT25 0x02000000
+#define MRC_BIT26 0x04000000
+#define MRC_BIT27 0x08000000
+#define MRC_BIT28 0x10000000
+#define MRC_BIT29 0x20000000
+#define MRC_BIT30 0x40000000
+#define MRC_BIT31 0x80000000
+#define MRC_BIT32 0x100000000ULL
+#define MRC_BIT33 0x200000000ULL
+#define MRC_BIT34 0x400000000ULL
+#define MRC_BIT35 0x800000000ULL
+#define MRC_BIT36 0x1000000000ULL
+#define MRC_BIT37 0x2000000000ULL
+#define MRC_BIT38 0x4000000000ULL
+#define MRC_BIT39 0x8000000000ULL
+#define MRC_BIT40 0x10000000000ULL
+#define MRC_BIT41 0x20000000000ULL
+#define MRC_BIT42 0x40000000000ULL
+#define MRC_BIT43 0x80000000000ULL
+#define MRC_BIT44 0x100000000000ULL
+#define MRC_BIT45 0x200000000000ULL
+#define MRC_BIT46 0x400000000000ULL
+#define MRC_BIT47 0x800000000000ULL
+#define MRC_BIT48 0x1000000000000ULL
+#define MRC_BIT49 0x2000000000000ULL
+#define MRC_BIT50 0x4000000000000ULL
+#define MRC_BIT51 0x8000000000000ULL
+#define MRC_BIT52 0x10000000000000ULL
+#define MRC_BIT53 0x20000000000000ULL
+#define MRC_BIT54 0x40000000000000ULL
+#define MRC_BIT55 0x80000000000000ULL
+#define MRC_BIT56 0x100000000000000ULL
+#define MRC_BIT57 0x200000000000000ULL
+#define MRC_BIT58 0x400000000000000ULL
+#define MRC_BIT59 0x800000000000000ULL
+#define MRC_BIT60 0x1000000000000000ULL
+#define MRC_BIT61 0x2000000000000000ULL
+#define MRC_BIT62 0x4000000000000000ULL
+#define MRC_BIT63 0x8000000000000000ULL
+
+#define MRC_DEADLOOP() { volatile int __iii; __iii = 1; while (__iii); }
+
+#ifndef ASM
+#define ASM __asm
+#endif
+
+///
+/// Type Max/Min Values
+///
+#define MRC_INT32_MAX (0x7FFFFFFF)
+#define MRC_INT32_MIN (0x80000000)
+#define MRC_INT64_MAX (0x7FFFFFFFFFFFFFFFLL)
+#define MRC_INT64_MIN (0x8000000000000000LL)
+#define MRC_UINT32_MAX (0xFFFFFFFF)
+#define MRC_UINT64_MAX (0xFFFFFFFFFFFFFFFFULL)
+#define MRC_UINT_MIN (0x0)
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.c
new file mode 100644
index 0000000000..1d438e3c85
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.c
@@ -0,0 +1,73 @@
+/** @file
+ DXE driver for Initializing SystemAgent Graphics ACPI table initialization.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "GraphicsInit.h"
+
+extern SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL mSaGlobalNvsAreaProtocol;
+
+
+/**
+Initialize GT ACPI tables
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SaPolicy - SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - GT ACPI initialization complete
+ @retval EFI_NOT_FOUND - Dxe System Table not found.
+ @retval EFI_OUT_OF_RESOURCES - Mmio not allocated successfully.
+**/
+EFI_STATUS
+GraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update IGD SA Global NVS
+ ///
+ DEBUG ((DEBUG_INFO, " Update Igd SA Global NVS Area.\n"));
+
+ mSaGlobalNvsAreaProtocol.Area->AlsEnable = GraphicsDxeConfig->AlsEnable;
+ ///
+ /// Initialize IGD state by checking if IGD Device 2 Function 0 is enabled in the chipset
+ ///
+ if (MmioRead16 (MmPciBase (SA_MC_BUS, 0, 0) + R_SA_DEVEN) & B_SA_DEVEN_D2EN_MASK) {
+ mSaGlobalNvsAreaProtocol.Area->IgdState = 1;
+ } else {
+ mSaGlobalNvsAreaProtocol.Area->IgdState = 0;
+ }
+
+ mSaGlobalNvsAreaProtocol.Area->BrightnessPercentage = 100;
+ mSaGlobalNvsAreaProtocol.Area->IgdBootType = GraphicsDxeConfig->IgdBootType;
+ mSaGlobalNvsAreaProtocol.Area->IgdPanelType = GraphicsDxeConfig->IgdPanelType;
+ mSaGlobalNvsAreaProtocol.Area->IgdPanelScaling = GraphicsDxeConfig->IgdPanelScaling;
+ ///
+ /// Get SFF power mode platform data for the IGD driver. Flip the bit (bitwise xor)
+ /// since Setup value is opposite of NVS and IGD OpRegion value.
+ ///
+ mSaGlobalNvsAreaProtocol.Area->IgdDvmtMemSize = GraphicsDxeConfig->IgdDvmtMemSize;
+ mSaGlobalNvsAreaProtocol.Area->IgdFunc1Enable = 0;
+ mSaGlobalNvsAreaProtocol.Area->IgdSciSmiMode = 0;
+ mSaGlobalNvsAreaProtocol.Area->GfxTurboIMON = GraphicsDxeConfig->GfxTurboIMON;
+
+ mSaGlobalNvsAreaProtocol.Area->EdpValid = 0;
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.h
new file mode 100644
index 0000000000..b76f775b24
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/GraphicsInit.h
@@ -0,0 +1,46 @@
+/** @file
+ Header file for initialization of GT PowerManagement
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _GRAPHICS_INIT_H_
+#define _GRAPHICS_INIT_H_
+
+#include <Library/DxeServicesTableLib.h>
+#include <Guid/DxeServices.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Library/MmPciLib.h>
+#include <SaAccess.h>
+#include <Protocol/SaPolicy.h>
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include <PchAccess.h>
+#include <CpuRegs.h>
+#include <Library/CpuPlatformLib.h>
+
+
+/**
+ Initialize GT ACPI tables
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SaPolicy - SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - GT ACPI initialization complete
+ @retval EFI_NOT_FOUND - Dxe System Table not found.
+ @retval EFI_OUT_OF_RESOURCES - Mmio not allocated successfully.
+**/
+EFI_STATUS
+GraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.c
new file mode 100644
index 0000000000..8e7ef7bc29
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.c
@@ -0,0 +1,525 @@
+/** @file
+ This is part of the implementation of an Intel Graphics drivers OpRegion /
+ Software SCI interface between system BIOS, ASL code, and Graphics drivers.
+ The code in this file will load the driver and initialize the interface
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Specification Reference:
+ - OpRegion / Software SCI SPEC
+**/
+///
+/// Include files
+///
+#include "IgdOpRegion.h"
+#include "CpuRegs.h"
+#include "Library/CpuPlatformLib.h"
+#include <Library/HobLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <SiConfigHob.h>
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED IGD_OPREGION_PROTOCOL mIgdOpRegion;
+GLOBAL_REMOVE_IF_UNREFERENCED SA_POLICY_PROTOCOL *mSaPolicy;
+
+///
+/// Function implementations.
+///
+/**
+ Get VBT data using SaPlaformPolicy
+
+ @param[in] VbtFileBuffer Pointer to VBT data buffer.
+
+ @retval EFI_SUCCESS VBT data was returned.
+ @retval EFI_NOT_FOUND VBT data not found.
+ @exception EFI_UNSUPPORTED Invalid signature in VBT data.
+**/
+EFI_STATUS
+GetIntegratedIntelVbtPtr (
+ OUT VBIOS_VBT_STRUCTURE **VbtFileBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS VbtAddress;
+ UINT32 Size;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+
+ ///
+ /// Get the SA policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaPolicyProtocolGuid,
+ NULL,
+ (VOID **) &mSaPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetConfigBlock ((VOID *) mSaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ VbtAddress = GraphicsDxeConfig->VbtAddress;
+ Size = GraphicsDxeConfig->Size;
+
+ if (VbtAddress == 0x00000000) {
+ return EFI_NOT_FOUND;
+ } else {
+ ///
+ /// Check VBT signature
+ ///
+ *VbtFileBuffer = NULL;
+ *VbtFileBuffer = (VBIOS_VBT_STRUCTURE *) (UINTN) VbtAddress;
+ if ((*((UINT32 *) ((*VbtFileBuffer)->HeaderSignature))) != VBT_SIGNATURE) {
+ FreePool (*VbtFileBuffer);
+ *VbtFileBuffer = NULL;
+ return EFI_UNSUPPORTED;
+ }
+ }
+ if (Size == 0) {
+ return EFI_NOT_FOUND;
+ } else {
+ ///
+ /// Check VBT size
+ ///
+ if ((*VbtFileBuffer)->HeaderVbtSize > Size) {
+ (*VbtFileBuffer)->HeaderVbtSize = (UINT16) Size;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get a pointer to an uncompressed image of the Intel video BIOS.
+
+ Note: This function would only be called if the video BIOS at 0xC000 is
+ missing or not an Intel video BIOS. It may not be an Intel video BIOS
+ if the Intel graphic contoller is considered a secondary adapter.
+
+ @param[in] VBiosImage - Pointer to an uncompressed Intel video BIOS. This pointer must
+ be set to NULL if an uncompressed image of the Intel Video BIOS
+ is not obtainable.
+
+ @retval EFI_SUCCESS - VBiosPtr is updated.
+ @exception EFI_UNSUPPORTED - No Intel video BIOS found.
+**/
+EFI_STATUS
+GetIntegratedIntelVBiosPtr (
+ OUT INTEL_VBIOS_OPTION_ROM_HEADER **VBiosImage
+ )
+{
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ INTEL_VBIOS_OPTION_ROM_HEADER *VBiosRomImage;
+ ///
+ /// Set as if an umcompressed Intel video BIOS image was not obtainable.
+ ///
+ VBiosRomImage = NULL;
+
+ ///
+ /// Get all PCI IO protocols
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Find the video BIOS by checking each PCI IO handle for an Intel video
+ /// BIOS OPROM.
+ ///
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ VBiosRomImage = PciIo->RomImage;
+
+ ///
+ /// If this PCI device doesn't have a ROM image, skip to the next device.
+ ///
+ if (!VBiosRomImage) {
+ continue;
+ }
+ ///
+ /// Get pointer to PCIR structure
+ ///
+ PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *) ((UINT8 *) VBiosRomImage + VBiosRomImage->PcirOffset);
+
+ ///
+ /// Check if we have an Intel video BIOS OPROM.
+ ///
+ if ((VBiosRomImage->Signature == OPTION_ROM_SIGNATURE) &&
+ (PcirBlockPtr->VendorId == V_SA_MC_VID) &&
+ (PcirBlockPtr->ClassCode[0] == 0x00) &&
+ (PcirBlockPtr->ClassCode[1] == 0x00) &&
+ (PcirBlockPtr->ClassCode[2] == 0x03)
+ ) {
+ ///
+ /// Found Intel video BIOS.
+ ///
+ *VBiosImage = VBiosRomImage;
+ return EFI_SUCCESS;
+ }
+ }
+ ///
+ /// No Intel video BIOS found.
+ ///
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size).
+ The VBT (Video BIOS Table) is a block of customizable data that is built
+ within the video BIOS and edited by customers.
+
+ @retval EFI_SUCCESS - Video BIOS VBT information returned.
+ @exception EFI_UNSUPPORTED - Could not find VBT information (*VBiosVbtPtr = NULL).
+**/
+EFI_STATUS
+GetVBiosVbtEndOfDxe (
+ VOID
+ )
+{
+ INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr;
+ UINT32 PcirBlockAddress;
+ UINT16 PciVenderId;
+ INTEL_VBIOS_OPTION_ROM_HEADER *VBiosPtr;
+ VBIOS_VBT_STRUCTURE *VBiosVbtPtr;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_STATUS Status;
+ VBIOS_VBT_STRUCTURE *VbtFileBuffer;
+ UINTN Index;
+ UINT8 LegacyVbtFound;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ SI_CONFIG_HOB *SiConfigHob;
+
+ VbtFileBuffer = NULL;
+ LegacyVbtFound = 1;
+
+ ///
+ /// Get the SA policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaPolicyProtocolGuid,
+ NULL,
+ (VOID **) &mSaPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetConfigBlock ((VOID *) mSaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ LegacyBios = NULL;
+ VBiosPtr = NULL;
+ //
+ // Get Silicon Config data HOB
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gSiConfigHobGuid);
+ SiConfigHob = (SI_CONFIG_HOB *)GET_GUID_HOB_DATA (HobPtr.Guid);
+ if (SiConfigHob->CsmFlag == 1) {
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+
+ if (LegacyBios) {
+ VBiosPtr = (INTEL_VBIOS_OPTION_ROM_HEADER *) (UINTN) (VBIOS_LOCATION_PRIMARY);
+ PcirBlockAddress = VBIOS_LOCATION_PRIMARY + VBiosPtr->PcirOffset;
+ PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *) (UINTN) (PcirBlockAddress);
+ PciVenderId = PcirBlockPtr->VendorId;
+ ///
+ /// If the video BIOS is not at 0xC0000 or it is not an Intel video BIOS get
+ /// the integrated Intel video BIOS (must be uncompressed).
+ ///
+ if ((VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != V_SA_MC_VID)) {
+ GetIntegratedIntelVBiosPtr (&VBiosPtr);
+ if (VBiosPtr != NULL) {
+ ///
+ /// Video BIOS found.
+ ///
+ PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->PcirOffset);
+ PciVenderId = PcirBlockPtr->VendorId;
+
+ if ((VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != V_SA_MC_VID)) {
+ ///
+ /// Intel video BIOS not found.
+ ///
+ VBiosVbtPtr = NULL;
+ LegacyVbtFound = 0;
+ }
+ }
+ }
+ }
+ }
+ if ((LegacyBios == NULL) || (LegacyVbtFound == 0)) {
+ ///
+ /// No Video BIOS found, try to get VBT from FV.
+ ///
+ GetIntegratedIntelVbtPtr (&VbtFileBuffer);
+ if (VbtFileBuffer != NULL) {
+ ///
+ /// Video BIOS not found, use VBT from SaPolicy
+ ///
+ DEBUG ((DEBUG_INFO, "VBT data found\n"));
+ for (Index = 0; (GraphicsDxeConfig->GopVersion[Index] != '\0'); Index++) {
+ }
+ Index = (Index+1)*2;
+ CopyMem (mIgdOpRegion.OpRegion->Header.DVER, GraphicsDxeConfig->GopVersion, Index);
+ CopyMem (mIgdOpRegion.OpRegion->VBT.GVD1, VbtFileBuffer, VbtFileBuffer->HeaderVbtSize);
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (VBiosPtr == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "VBIOS found at 0x%X\n", VBiosPtr));
+ VBiosVbtPtr = (VBIOS_VBT_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->VbtOffset);
+
+ if ((*((UINT32 *) (VBiosVbtPtr->HeaderSignature))) != VBT_SIGNATURE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// Initialize Video BIOS version with its build number.
+ ///
+ mIgdOpRegion.OpRegion->Header.VVER[0] = VBiosVbtPtr->CoreBlockBiosBuild[0];
+ mIgdOpRegion.OpRegion->Header.VVER[1] = VBiosVbtPtr->CoreBlockBiosBuild[1];
+ mIgdOpRegion.OpRegion->Header.VVER[2] = VBiosVbtPtr->CoreBlockBiosBuild[2];
+ mIgdOpRegion.OpRegion->Header.VVER[3] = VBiosVbtPtr->CoreBlockBiosBuild[3];
+ CopyMem (mIgdOpRegion.OpRegion->VBT.GVD1, VBiosVbtPtr, VBiosVbtPtr->HeaderVbtSize);
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Graphics OpRegion / Software SCI driver installation function.
+
+ @param[in] void - None
+ @retval EFI_SUCCESS - The driver installed without error.
+ @retval EFI_ABORTED - The driver encountered an error and could not complete
+ installation of the ACPI tables.
+**/
+EFI_STATUS
+IgdOpRegionInit (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINT32 DwordData;
+ UINTN IgdBaseAddress;
+ UINT32 Data32;
+ UINT16 PchAcpiBaseAddress;
+ UINT16 PchTcoBaseAddress;
+ SA_POLICY_PROTOCOL *SaPolicy;
+ CPU_SKU CpuSku;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL *SaGlobalNvsArea;
+
+ CpuSku = GetCpuSku ();
+
+ ///
+ /// Get the SA policy.
+ ///
+ Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **)&SaPolicy);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Locate the SA Global NVS Protocol.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &SaGlobalNvsArea
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Allocate an ACPI NVS memory buffer as the IGD OpRegion, zero initialize
+ /// the first 1K, and set the IGD OpRegion pointer in the Global NVS
+ /// area structure.
+ ///
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (IGD_OPREGION_STRUC), (VOID **) &mIgdOpRegion.OpRegion);
+ ASSERT_EFI_ERROR (Status);
+
+ SetMem (mIgdOpRegion.OpRegion, 0x2000, 0);
+ SaGlobalNvsArea->Area->IgdOpRegionAddress = (UINT32) (UINTN) (mIgdOpRegion.OpRegion);
+
+ ///
+ /// If IGD is disabled return
+ ///
+ IgdBaseAddress = MmPciBase (SA_IGD_BUS, SA_IGD_DEV, SA_IGD_FUN_0);
+ if (MmioRead32 (IgdBaseAddress + 0) == 0xFFFFFFFF) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Initialize OpRegion Header
+ ///
+ CopyMem (mIgdOpRegion.OpRegion->Header.SIGN, HEADER_SIGNATURE, sizeof (HEADER_SIGNATURE));
+ ///
+ /// Set OpRegion Size in KBs
+ ///
+ mIgdOpRegion.OpRegion->Header.SIZE = HEADER_SIZE / 1024;
+ mIgdOpRegion.OpRegion->Header.OVER = (UINT32) (LShiftU64 (HEADER_OPREGION_VER, 16) + LShiftU64 (HEADER_OPREGION_REV, 8));
+
+ ///
+ /// All Mailboxes are supported.
+ ///
+ mIgdOpRegion.OpRegion->Header.MBOX = HEADER_MBOX_SUPPORT;
+
+ ///
+ /// Initialize OpRegion Mailbox 1 (Public ACPI Methods).
+ ///
+ /// Note - The initial setting of mailbox 1 fields is implementation specific.
+ /// Adjust them as needed many even coming from user setting in setup.
+ ///
+ mIgdOpRegion.OpRegion->MBox1.CLID = LID_OPEN;
+
+ ///
+ /// Initialize OpRegion Mailbox 3 (ASLE Interrupt and Power Conservation).
+ ///
+ /// Note - The initial setting of mailbox 3 fields is implementation specific.
+ /// Adjust them as needed many even coming from user setting in setup.
+ ///
+ ///
+ /// Do not initialize TCHE. This field is written by the graphics driver only.
+ ///
+ ///
+ /// The ALSI field is generally initialized by ASL code by reading the embedded controller.
+ ///
+ mIgdOpRegion.OpRegion->Header.PCON = GraphicsDxeConfig->PlatformConfig;
+ if (CpuSku != EnumCpuTrad) {
+ mIgdOpRegion.OpRegion->Header.PCON = mIgdOpRegion.OpRegion->Header.PCON | 0x2;
+ }
+
+ mIgdOpRegion.OpRegion->MBox3.BCLP = BACKLIGHT_BRIGHTNESS;
+
+ mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH);
+
+ ///
+ /// Reporting to driver for VR IMON Calibration. Bits [5-1] values supported 14A to 31A.
+ ///
+ mIgdOpRegion.OpRegion->MBox3.PCFT = (SaGlobalNvsArea->Area->GfxTurboIMON << 1) & 0x003E;
+
+ ///
+ /// Set Initial current Brightness
+ ///
+ mIgdOpRegion.OpRegion->MBox3.CBLV = (INIT_BRIGHT_LEVEL | FIELD_VALID_BIT);
+
+ ///
+ /// <EXAMPLE> Create a static Backlight Brightness Level Duty cycle Mapping Table
+ /// Possible 20 entries (example used 10), each 16 bits as follows:
+ /// [15] = Field Valid bit, [14:08] = Level in Percentage (0-64h), [07:00] = Desired duty cycle (0 - FFh).
+ ///
+ mIgdOpRegion.OpRegion->MBox3.BCLM[0] = (0x0000 + WORD_FIELD_VALID_BIT); ///< 0%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[1] = (0x0A19 + WORD_FIELD_VALID_BIT); ///< 10%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[2] = (0x1433 + WORD_FIELD_VALID_BIT); ///< 20%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[3] = (0x1E4C + WORD_FIELD_VALID_BIT); ///< 30%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[4] = (0x2866 + WORD_FIELD_VALID_BIT); ///< 40%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[5] = (0x327F + WORD_FIELD_VALID_BIT); ///< 50%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[6] = (0x3C99 + WORD_FIELD_VALID_BIT); ///< 60%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[7] = (0x46B2 + WORD_FIELD_VALID_BIT); ///< 70%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[8] = (0x50CC + WORD_FIELD_VALID_BIT); ///< 80%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[9] = (0x5AE5 + WORD_FIELD_VALID_BIT); ///< 90%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[10] = (0x64FF + WORD_FIELD_VALID_BIT); ///< 100%
+
+ mIgdOpRegion.OpRegion->MBox3.IUER = 0x00;
+
+ if (!EFI_ERROR (Status)) {
+ mIgdOpRegion.OpRegion->MBox3.IUER = GraphicsDxeConfig->IuerStatusVal;
+ }
+
+ ///
+ /// Initialize hardware state:
+ /// Set ASLS Register to the OpRegion physical memory address.
+ /// Set SWSCI register bit 15 to a "1" to activate SCI interrupts.
+ ///
+ MmioWrite32 (IgdBaseAddress + R_SA_IGD_ASLS_OFFSET, (UINT32) (UINTN) (mIgdOpRegion.OpRegion));
+ MmioAndThenOr16 (IgdBaseAddress + R_SA_IGD_SWSCI_OFFSET, (UINT16) ~(BIT0), BIT15);
+
+ DwordData = MmioRead32 (IgdBaseAddress + R_SA_IGD_ASLS_OFFSET);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (IgdBaseAddress + R_SA_IGD_ASLS_OFFSET),
+ 1,
+ &DwordData
+ );
+ DwordData = MmioRead32 (IgdBaseAddress + R_SA_IGD_SWSCI_OFFSET);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (IgdBaseAddress + R_SA_IGD_SWSCI_OFFSET),
+ 1,
+ &DwordData
+ );
+
+ PchAcpiBaseGet (&PchAcpiBaseAddress);
+ PchTcoBaseGet (&PchTcoBaseAddress);
+ ///
+ /// Clear the B_DMISCI_STS bit in R_TCO1_STS by writing a '1'.
+ ///
+ IoWrite16 ((UINTN) (PchTcoBaseAddress + R_PCH_TCO1_STS), B_PCH_TCO1_STS_DMISCI);
+
+ ///
+ /// Clear the ACPI TCO status.
+ ///
+ Data32 = B_PCH_ACPI_GPE0_STS_127_96_TC0SCI;
+ IoWrite32 ((UINTN) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0_STS_127_96), Data32);
+
+ ///
+ /// Enable ACPI TCO SCI's.
+ ///
+ IoOr16 ((UINTN) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0_EN_127_96), B_PCH_ACPI_GPE0_EN_127_96_TC0SCI);
+
+ ///
+ /// Install OpRegion / Software SCI protocol
+ ///
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gIgdOpRegionProtocolGuid,
+ &mIgdOpRegion,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.h
new file mode 100644
index 0000000000..40616c4b82
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/IgdOpRegion.h
@@ -0,0 +1,189 @@
+/** @file
+ This is part of the implementation of an Intel Graphics drivers OpRegion /
+ Software SCI interface between system BIOS, ASL code, and Graphics drivers.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Specification Reference:
+ - OpRegion / Software SCI SPEC
+**/
+#ifndef _IGD_OPREGION_H_
+#define _IGD_OPREGION_H_
+
+///
+/// Statements that include other header files.
+///
+#include <Uefi/UefiBaseType.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciLib.h>
+#include <Library/IoLib.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LegacyBios.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <SaAccess.h>
+#include <IndustryStandard/Pci22.h>
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include <Protocol/SaPolicy.h>
+
+
+#include <Protocol/SaGlobalNvsArea.h>
+
+///
+/// Driver Produced Protocol Prototypes
+///
+#include <Protocol/IgdOpRegion.h>
+
+///
+///
+/// OpRegion (Miscellaneous) defines.
+///
+/// OpRegion Header defines.
+///
+typedef UINT16 STRING_REF;
+#define HEADER_SIGNATURE "IntelGraphicsMem"
+#define HEADER_SIZE 0x2000
+#define HEADER_OPREGION_VER 0x0200
+#define HEADER_OPREGION_REV 0x00
+#define HEADER_MBOX_SUPPORT (HD_MBOX5 + HD_MBOX4 + HD_MBOX3 + HD_MBOX2 + HD_MBOX1)
+#define HD_MBOX1 BIT0
+#define HD_MBOX2 BIT1
+#define HD_MBOX3 BIT2
+#define HD_MBOX4 BIT3
+#define HD_MBOX5 BIT4
+#define SVER_SIZE 32
+
+///
+/// OpRegion Mailbox 1 EQUates.
+///
+#define LID_OPEN 3
+
+///
+/// OpRegion Mailbox 3 EQUates.
+///
+#define ALS_ENABLE BIT0
+#define BLC_ENABLE BIT1
+#define BACKLIGHT_BRIGHTNESS 0xFF
+#define FIELD_VALID_BIT BIT31
+#define WORD_FIELD_VALID_BIT BIT15
+#define PFIT_ENABLE BIT2
+#define PFIT_OPRN_AUTO 0x00000000
+#define PFIT_OPRN_SCALING 0x00000007
+#define PFIT_OPRN_OFF 0x00000000
+#define PFIT_SETUP_AUTO 0
+#define PFIT_SETUP_SCALING 1
+#define PFIT_SETUP_OFF 2
+#define INIT_BRIGHT_LEVEL 0x64
+#define PFIT_STRETCH 6
+
+///
+/// Video BIOS / VBT defines
+///
+#define OPTION_ROM_SIGNATURE 0xAA55
+#define VBIOS_LOCATION_PRIMARY 0xC0000
+
+#define VBT_SIGNATURE SIGNATURE_32 ('$', 'V', 'B', 'T')
+///
+/// Typedef stuctures
+///
+#pragma pack(1)
+typedef struct {
+ UINT16 Signature; /// 0xAA55
+ UINT8 Size512;
+ UINT8 Reserved[21];
+ UINT16 PcirOffset;
+ UINT16 VbtOffset;
+} INTEL_VBIOS_OPTION_ROM_HEADER;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct {
+ UINT32 Signature; /// "PCIR"
+ UINT16 VendorId; /// 0x8086
+ UINT16 DeviceId;
+ UINT16 Reserved0;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 Reserved1;
+} INTEL_VBIOS_PCIR_STRUCTURE;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct {
+ UINT8 HeaderSignature[20];
+ UINT16 HeaderVersion;
+ UINT16 HeaderSize;
+ UINT16 HeaderVbtSize;
+ UINT8 HeaderVbtCheckSum;
+ UINT8 HeaderReserved;
+ UINT32 HeaderOffsetVbtDataBlock;
+ UINT32 HeaderOffsetAim1;
+ UINT32 HeaderOffsetAim2;
+ UINT32 HeaderOffsetAim3;
+ UINT32 HeaderOffsetAim4;
+ UINT8 DataHeaderSignature[16];
+ UINT16 DataHeaderVersion;
+ UINT16 DataHeaderSize;
+ UINT16 DataHeaderDataBlockSize;
+ UINT8 CoreBlockId;
+ UINT16 CoreBlockSize;
+ UINT16 CoreBlockBiosSize;
+ UINT8 CoreBlockBiosType;
+ UINT8 CoreBlockReleaseStatus;
+ UINT8 CoreBlockHWSupported;
+ UINT8 CoreBlockIntegratedHW;
+ UINT8 CoreBlockBiosBuild[4];
+ UINT8 CoreBlockBiosSignOn[155];
+} VBIOS_VBT_STRUCTURE;
+#pragma pack()
+///
+/// Driver Private Function definitions
+///
+
+/**
+ Graphics OpRegion / Software SCI driver installation function.
+
+ @retval EFI_SUCCESS - The driver installed without error.
+ @retval EFI_ABORTED - The driver encountered an error and could not complete
+ installation of the ACPI tables.
+**/
+EFI_STATUS
+IgdOpRegionInit (
+ VOID
+ );
+
+/**
+ Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size).
+ The VBT (Video BIOS Table) is a block of customizable data that is built
+ within the video BIOS and edited by customers.
+
+ @retval EFI_SUCCESS - Video BIOS VBT information returned.
+ @exception EFI_UNSUPPORTED - Could not find VBT information (*VBiosVbtPtr = NULL).
+**/
+EFI_STATUS
+GetVBiosVbtEndOfDxe (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
new file mode 100644
index 0000000000..4c7fc08200
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
@@ -0,0 +1,304 @@
+/** @file
+ This is the driver that initializes the Intel System Agent.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include <Protocol/SaGlobalNvsArea.h>
+
+///
+/// Global Variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL mSaGlobalNvsAreaProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED SA_POLICY_PROTOCOL *mSaPolicy;
+
+/**
+ Initialize System Agent SSDT ACPI tables
+
+ @retval EFI_SUCCESS ACPI tables are initialized successfully
+ @retval EFI_NOT_FOUND ACPI tables not found
+**/
+EFI_STATUS
+InitializeSaSsdtAcpiTables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN AcpiTableKey;
+ UINT8 *CurrPtr;
+ UINT8 *EndPtr;
+ UINT32 *Signature;
+ EFI_ACPI_DESCRIPTION_HEADER *SaAcpiTable;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+
+ FwVol = NULL;
+ SaAcpiTable = NULL;
+
+ ///
+ /// Locate ACPI Table protocol
+ ///
+ DEBUG ((DEBUG_INFO, "Init SA SSDT table\n"));
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_WARN, "Fail to locate EfiAcpiTableProtocol.\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ ///
+ /// Locate protocol.
+ /// There is little chance we can't find an FV protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Looking for FV with ACPI storage file
+ ///
+ for (i = 0; i < NumberOfHandles; i++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &gSaSsdtAcpiTableStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ ///
+ /// If we found it, then we are done
+ ///
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol != NULL);
+ if (FwVol == NULL) {
+ DEBUG ((DEBUG_INFO, "SA Global NVS table not found\n"));
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Our exit status is determined by the success of the previous operations
+ /// If the protocol was found, Instance already points to it.
+ /// Read tables from the storage file.
+ ///
+ Instance = 0;
+ CurrentTable = NULL;
+ while (Status == EFI_SUCCESS) {
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gSaSsdtAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID **) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Check the table ID to modify the table
+ ///
+ if (((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->OemTableId == SIGNATURE_64 ('S', 'a', 'S', 's', 'd', 't', ' ', 0)) {
+ SaAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ ///
+ /// Locate the SSDT package
+ ///
+ CurrPtr = (UINT8 *) SaAcpiTable;
+ EndPtr = CurrPtr + SaAcpiTable->Length;
+
+ for (; CurrPtr <= EndPtr; CurrPtr++) {
+ Signature = (UINT32 *) (CurrPtr + 3);
+ if (*Signature == SIGNATURE_32 ('S', 'A', 'N', 'V')) {
+ ASSERT (*(UINT32 *) (CurrPtr + 3 + sizeof (*Signature) + 2) == 0xFFFF0000);
+ ASSERT (*(UINT16 *) (CurrPtr + 3 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) == 0xAA55);
+ ///
+ /// SA Global NVS Area address
+ ///
+ *(UINT32 *) (CurrPtr + 3 + sizeof (*Signature) + 2) = (UINT32) (UINTN) mSaGlobalNvsAreaProtocol.Area;
+ ///
+ /// SA Global NVS Area size
+ ///
+ *(UINT16 *) (CurrPtr + 3 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) =
+ sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA);
+
+ AcpiTableKey = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ SaAcpiTable,
+ SaAcpiTable->Length,
+ &AcpiTableKey
+ );
+ ASSERT_EFI_ERROR (Status);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ ///
+ /// Increment the instance
+ ///
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+ return Status;
+
+}
+
+/**
+ This function gets registered as a callback to perform Dmar Igd
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+SaAcpiEndOfDxeCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ UpdateDmarEndOfDxe ();
+
+ if (MmioRead16 (MmPciBase (SA_MC_BUS, 2, 0) + R_SA_IGD_VID) != 0xFFFF) {
+ Status = GetVBiosVbtEndOfDxe ();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((DEBUG_WARN, "[SA] EndOfDxe Op Region Error, Status = %r \n", Status));
+ }
+
+ }
+
+ return;
+}
+
+/**
+ SystemAgent Acpi Initialization.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
+ ///
+ /// Get the platform setup policy.
+ ///
+ Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &mSaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Install System Agent Global NVS protocol
+ ///
+ DEBUG ((DEBUG_INFO, "Install SA GNVS protocol\n"));
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA), (VOID **) &mSaGlobalNvsAreaProtocol.Area);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem ((VOID *) mSaGlobalNvsAreaProtocol.Area, sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA));
+ mSaGlobalNvsAreaProtocol.Area->XPcieCfgBaseAddress = (UINT32) (MmPciBase (0, 0, 0));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gSaGlobalNvsAreaProtocolGuid,
+ &mSaGlobalNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ ///
+ /// GtPostInit Initialization
+ ///
+ DEBUG ((DEBUG_INFO, "Initializing GT ACPI tables\n"));
+ GraphicsInit (ImageHandle, mSaPolicy);
+
+ ///
+ /// Vtd Initialization
+ ///
+ DEBUG ((DEBUG_INFO, "Initializing VT-d ACPI tables\n"));
+ VtdInit (mSaPolicy);
+
+ ///
+ /// IgdOpRegion Install Initialization
+ ///
+ DEBUG ((DEBUG_INFO, "Initializing IGD OpRegion\n"));
+ IgdOpRegionInit ();
+
+ ///
+ /// Register an end of DXE event for SA ACPI to do tasks before invoking any UEFI drivers,
+ /// applications, or connecting consoles,...
+ ///
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ SaAcpiEndOfDxeCallback,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+
+ ///
+ /// Install System Agent Global NVS ACPI table
+ ///
+ Status = InitializeSaSsdtAcpiTables ();
+
+
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
new file mode 100644
index 0000000000..7e9efc40bc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
@@ -0,0 +1,33 @@
+/** @file
+ Header file for SA Common Initialization Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_INITIALIZATION_DRIVER_H_
+#define _SA_INITIALIZATION_DRIVER_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/Acpi.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/SaPlatformLib.h>
+#include <Guid/EventGroup.h>
+#include <CpuRegs.h>
+#include <SaAccess.h>
+#include <Library/CpuPlatformLib.h>
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
new file mode 100644
index 0000000000..6900cf8a5b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
@@ -0,0 +1,47 @@
+/** @file
+ This is the driver that initializes the Intel System Agent.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include <Library/MmPciLib.h>
+#include <MemInfoHob.h>
+
+/**
+ SystemAgent Dxe Initialization.
+
+ @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 No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "SaInitDxe Start\n"));
+
+
+ Status = SaAcpiInit (ImageHandle);
+
+
+ DEBUG ((DEBUG_INFO, "SaInitDxe End\n"));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
new file mode 100644
index 0000000000..55a87fef4d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
@@ -0,0 +1,102 @@
+/** @file
+ Header file for SA Initialization Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SA_INITIALIZATION_DXE_DRIVER_H_
+#define _SA_INITIALIZATION_DXE_DRIVER_H_
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+#include "VTd.h"
+#include "IgdOpRegion.h"
+#include "GraphicsInit.h"
+#include <Library/HobLib.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <SiConfigHob.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/MmPciLib.h>
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include <Protocol/SaPolicy.h>
+
+extern EFI_GUID gSaSsdtAcpiTableStorageGuid;
+
+/**
+ <b>System Agent Initialization DXE Driver Entry Point</b>
+ - <b>Introduction</b> \n
+ Based on the information/data in SA_POLICY_PROTOCOL, this module performs further SA initialization in DXE phase,
+ e.g. internal devices enable/disable, SSVID/SID programming, graphic power-management, VT-d, IGD OpRegion initialization.
+ From the perspective of a PCI Express hierarchy, the Broadwell System Agent and PCH together appear as a Root Complex with root ports the number of which depends on how the 8 PCH ports and 4 System Agent PCIe ports are configured [4x1, 2x8, 1x16].
+ There is an internal link (DMI or OPI) that connects the System Agent to the PCH component. This driver includes initialization of SA DMI, PCI Express, SA & PCH Root Complex Topology.
+ For iGFX, this module implements the initialization of the Graphics Technology Power Management from the Broadwell System Agent BIOS Specification and the initialization of the IGD OpRegion/Software SCI - BIOS Specification.
+ The ASL files that go along with the driver define the IGD OpRegion mailboxes in ACPI space and implement the software SCI interrupt mechanism.
+ The IGD OpRegion/Software SCI code serves as a communication interface between system BIOS, ASL, and Intel graphics driver including making a block of customizable data (VBT) from the Intel video BIOS available.
+ Reference Code for the SCI service functions "Get BIOS Data" and "System BIOS Callback" can be found in the ASL files, those functions can be platform specific, the sample provided in the reference code are implemented for Intel CRB.
+ This module implements the VT-d functionality described in the Broadwell System Agent BIOS Specification.
+ This module publishes the LegacyRegion protocol to control the read and write accesses to the Legacy BIOS ranges.
+ E000 and F000 segments are the legacy BIOS ranges and contain pointers to the ACPI regions, SMBIOS tables and so on. This is a private protocol used by Intel Framework.
+ This module registers CallBack function that performs SA security registers lockdown at end of post as required from Broadwell Bios Spec.
+ In addition, this module publishes the SaInfo Protocol with information such as current System Agent reference code version#.
+
+ - @pre
+ - EFI_FIRMWARE_VOLUME_PROTOCOL: Documented in Firmware Volume Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ - SA_POLICY_PROTOCOL: A protocol published by a platform DXE module executed earlier; this is documented in this document as well.
+ - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+ - EFI_BOOT_SCRIPT_SAVE_PROTOCOL: A protocol published by a platform DXE module executed earlier; refer to the Sample Code section of the Framework PCH Reference Code.
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+ - EFI_ACPI_TABLE_PROTOCOL : Documented in PI Specification 1.2
+ - EFI_CPU_IO_PROTOCOL: Documented in CPU I/O Protocol Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ - EFI_DATA_HUB_PROTOCOL: Documented in EFI Data Hub Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ - EFI_HII_PROTOCOL (or EFI_HII_DATABASE_PROTOCOL for UEFI 2.1): Documented in Human Interface Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ (For EFI_HII_DATABASE_PROTOCOL, refer to UEFI Specification Version 2.1 available at the URL: http://www.uefi.org/)
+
+ - @result
+ IGD power-management functionality is initialized; VT-d is initialized (meanwhile, the DMAR table is updated); IGD OpRegion is initialized - IGD_OPREGION_PROTOCOL installed, IGD OpRegion allocated and mailboxes initialized, chipset initialized and ready to generate Software SCI for Internal graphics events. Publishes the SA_INFO_PROTOCOL with current SA reference code version #. Publishes the EFI_LEGACY_REGION_PROTOCOL documented in the Compatibility Support Module Specification, version 0.9, available at the URL: http://www.intel.com/technology/framework/spec.htm
+
+ - <b>References</b> \n
+ IGD OpRegion/Software SCI for Broadwell
+ Advanced Configuration and Power Interface Specification Revision 4.0a.
+
+ - <b>Porting Recommendations</b> \n
+ No modification of the DXE driver should be typically necessary.
+ This driver should be executed after all related devices (audio, video, ME, etc.) are initialized to ensure correct data in DMAR table and DMA-remapping registers.
+
+ @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 No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ SystemAgent Acpi Initialization.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf
new file mode 100644
index 0000000000..6b01b494cd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf
@@ -0,0 +1,109 @@
+## @file
+# Component description file for SystemAgent Initialization driver
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SaInitDxe
+FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE811
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = SaInitEntryPointDxe
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+
+
+[LibraryClasses]
+UefiDriverEntryPoint
+UefiLib
+UefiBootServicesTableLib
+DxeServicesTableLib
+DebugLib
+TimerLib
+PciLib
+BaseMemoryLib
+MemoryAllocationLib
+CpuPlatformLib
+IoLib
+S3BootScriptLib
+MmPciLib
+PchCycleDecodingLib
+PchP2sbLib
+GpioLib
+ConfigBlockLib
+SaPlatformLib
+HobLib
+PchPcieRpLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemId
+gSiPkgTokenSpaceGuid.PcdMchBaseAddress
+
+[Sources]
+SaInitDxe.h
+SaInitDxe.c
+SaInit.h
+IgdOpRegion.h
+IgdOpRegion.c
+GraphicsInit.h
+GraphicsInit.c
+SaAcpi.c
+VTd.c
+VTd.h
+
+
+[Protocols]
+gEfiAcpiTableProtocolGuid ## CONSUMES
+gSaGlobalNvsAreaProtocolGuid ## PRODUCES
+gSaPolicyProtocolGuid ## CONSUMES
+gEfiCpuArchProtocolGuid ## CONSUMES
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gEfiPciIoProtocolGuid ## CONSUMES
+gEfiGlobalNvsAreaProtocolGuid ## CONSUMES
+gIgdOpRegionProtocolGuid ## PRODUCES
+gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
+gEfiLegacyBiosProtocolGuid ## CONSUMES
+
+[Guids]
+gSaConfigHobGuid
+gSaAcpiTableStorageGuid
+gMiscDxeConfigGuid
+gSaSsdtAcpiTableStorageGuid
+gEfiEndOfDxeEventGroupGuid
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+gGraphicsDxeConfigGuid
+
+[Depex]
+gEfiAcpiTableProtocolGuid AND
+gEfiFirmwareVolume2ProtocolGuid AND
+gSaPolicyProtocolGuid AND
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiHiiDatabaseProtocolGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.c
new file mode 100644
index 0000000000..ded44b661f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.c
@@ -0,0 +1,931 @@
+/** @file
+ This code provides a initialization of intel VT-d (Virtualization Technology for Directed I/O).
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include "VTd.h"
+#include <CpuRegs.h>
+#include <SaConfigHob.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchInfoLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED SA_POLICY_PROTOCOL *mSaPolicy;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *mPchConfigHob;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SERIES mPchSeries;
+GLOBAL_REMOVE_IF_UNREFERENCED SA_CONFIG_HOB *SaConfigHob;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddI2C0Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddI2C1Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddI2C2Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddI2C3Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddI2C4Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddI2C5Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddSpi0Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddSpi1Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddUa00Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddUa01Needed;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAnddUa02Needed;
+
+/**
+ For device that specified by Device Num and Function Num,
+ mDevEnMap is used to check device presence.
+ 0x80 means use Device ID to detemine presence
+
+ The structure is used to check if device scope is valid when update DMAR table
+**/
+UINT16 mDevEnMap[][2] = {{0x0200, 0x80}, {0x1400, 0x80}, {0x1401, 0x80}};
+
+BOOLEAN mInterruptRemappingSupport;
+
+/**
+ Get the corresponding device Enable/Disable bit according DevNum and FunNum
+
+ @param[in] DevNum - Device Number
+ @param[in] FunNum - Function Number
+
+ @retval If the device is found, return disable/Enable bit in FD/Deven reigster
+ @retval If not found return 0xFF
+**/
+UINT16
+GetFunDisableBit (
+ UINT8 DevNum,
+ UINT8 FunNum
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof (mDevEnMap) / 4; Index++) {
+ if (mDevEnMap[Index][0] == ((DevNum << 0x08) | FunNum)) {
+ return mDevEnMap[Index][1];
+ }
+ }
+
+ return 0xFF;
+}
+
+/**
+ Update the DRHD structure
+
+ @param[in, out] DrhdEnginePtr - A pointer to DRHD structure
+**/
+VOID
+UpdateDrhd (
+ IN OUT VOID *DrhdEnginePtr
+ )
+{
+ UINT16 Length;
+ UINT16 DisableBit;
+ UINTN DeviceScopeNum;
+ BOOLEAN NeedRemove;
+ EFI_ACPI_DRHD_ENGINE1_STRUCT *DrhdEngine;
+
+ //
+ // Convert DrhdEnginePtr to EFI_ACPI_DRHD_ENGINE1_STRUCT Pointer
+ //
+ DrhdEngine = (EFI_ACPI_DRHD_ENGINE1_STRUCT *) DrhdEnginePtr;
+ Length = DrhdEngine->Length;
+ DeviceScopeNum = (DrhdEngine->Length - EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ DisableBit = GetFunDisableBit (
+ DrhdEngine->DeviceScope[0].PciPath[0],
+ DrhdEngine->DeviceScope[0].PciPath[1]
+ );
+ NeedRemove = FALSE;
+ if ((DisableBit == 0xFF) ||
+ (DrhdEngine->RegisterBaseAddress == 0) ||
+ ((DisableBit == 0x80) &&
+ (MmioRead32 (MmPciBase (0, DrhdEngine->DeviceScope[0].PciPath[0], DrhdEngine->DeviceScope[0].PciPath[1]) + 0x00) == 0xFFFFFFFF))
+ ) {
+ NeedRemove = TRUE;
+ }
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ }
+ ///
+ /// If no devicescope is left, we set the structure length as 0x00
+ ///
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->Flags == 0x01)) {
+ DrhdEngine->Length = Length;
+ } else {
+ DrhdEngine->Length = 0;
+ }
+}
+
+/**
+ Get IOAPIC ID from LPC
+
+ @retval APIC ID
+**/
+UINT8
+GetIoApicId (
+ VOID
+ )
+{
+ UINT8 volatile *IoapicIndex;
+ UINT32 volatile *IoapicData;
+ UINT32 IoApicIndexAddr;
+ UINT32 IoApicDataAddr;
+ UINT32 Data32;
+
+ ///
+ /// Get IOAPIC base
+ ///
+ PchIoApicBaseGet (&IoApicIndexAddr, &IoApicDataAddr);
+ IoapicIndex = (UINT8 *) (UINTN) IoApicIndexAddr;
+ IoapicData = (UINT32 *) (UINTN) IoApicDataAddr;
+
+ ///
+ /// Get APIC ID from Identification Register (Index 0)
+ ///
+ *IoapicIndex = 0;
+ Data32 = (*IoapicData & 0x0F000000) >> 24;
+
+ return (UINT8) Data32;
+}
+
+/**
+ Initialize some data required for ANDD table generation.
+
+**/
+VOID
+AnddTablePreInit (
+ VOID
+ )
+{
+ /*
+ For Serial IO devices, they do not appear in PCI space, use platform policy or SPT SKU to determine existence
+ - I2C0 (D21: F0)
+ - I2C1 (D21: F1)
+ - I2C2 (D21: F2) (LP Only)
+ - I2C3 (D21: F3) (LP Only)
+ - I2C4 (D25: F2) (LP Only)
+ - I2C5 (D25: F1) (LP Only)
+ - SPI0 (D30: F2)
+ - SPI1 (D30: F3)
+ - UART0 (D30: F0)
+ - UART1 (D30: F1)
+ - UART2 (D25: F0)
+ - PEMC (D30: F4) (LP Only) (PCI mode only)
+ - PSDO (D30: F5) (LP Only) (Deprecated)
+ - PSDC (D30: F6) (LP Only) (PCI mode only)
+ */
+ mAnddI2C0Needed = TRUE;
+ mAnddI2C1Needed = TRUE;
+ mAnddI2C2Needed = TRUE;
+ mAnddI2C3Needed = TRUE;
+ mAnddI2C4Needed = TRUE;
+ mAnddI2C5Needed = TRUE;
+ mAnddSpi0Needed = TRUE;
+ mAnddSpi1Needed = TRUE;
+ mAnddUa00Needed = TRUE;
+ mAnddUa01Needed = TRUE;
+ mAnddUa02Needed = TRUE;
+
+ if (mPchConfigHob->SerialIo.DevMode[0] != 2) {
+ mAnddI2C0Needed = FALSE;
+ if (mPchConfigHob->SerialIo.DevMode[0] == 0) {
+ //
+ // Function 0 disabled so no sub-functions
+ //
+ mAnddI2C1Needed = FALSE;
+ mAnddI2C2Needed = FALSE;
+ mAnddI2C3Needed = FALSE;
+ }
+ }
+ if (mPchConfigHob->SerialIo.DevMode[1] != 2) {
+ mAnddI2C1Needed = FALSE;
+ }
+ if ((mPchSeries != PchLp) || (mPchConfigHob->SerialIo.DevMode[2] != 2)) {
+ mAnddI2C2Needed = FALSE;
+ }
+ if ((mPchSeries != PchLp) || (mPchConfigHob->SerialIo.DevMode[3] != 2)) {
+ mAnddI2C3Needed = FALSE;
+ }
+ if ((mPchSeries != PchLp) || (mPchConfigHob->SerialIo.DevMode[4] != 2)) {
+ mAnddI2C4Needed = FALSE;
+ }
+ if ((mPchSeries != PchLp) || (mPchConfigHob->SerialIo.DevMode[5] != 2)) {
+ mAnddI2C5Needed = FALSE;
+ }
+ if (mPchConfigHob->SerialIo.DevMode[6] != 2) {
+ mAnddSpi0Needed = FALSE;
+ }
+ if (mPchConfigHob->SerialIo.DevMode[7] != 2) {
+ mAnddSpi1Needed = FALSE;
+ }
+ if (mPchConfigHob->SerialIo.DevMode[8] != 2) {
+ mAnddUa00Needed = FALSE;
+ if (mPchConfigHob->SerialIo.DevMode[8] == 0) {
+ //
+ // Function 0 disabled so no sub-functions
+ //
+ mAnddUa01Needed = FALSE;
+ mAnddSpi0Needed = FALSE;
+ mAnddSpi1Needed = FALSE;
+ }
+ }
+ if (mPchConfigHob->SerialIo.DevMode[9] != 2) {
+ mAnddUa01Needed = FALSE;
+ }
+ if (mPchConfigHob->SerialIo.DevMode[10] != 2) {
+ mAnddUa02Needed = FALSE;
+ if (mPchConfigHob->SerialIo.DevMode[10] == 0) {
+ //
+ // Function 0 disabled so no sub-functions
+ //
+ mAnddI2C4Needed = FALSE;
+ mAnddI2C5Needed = FALSE;
+ }
+ }
+}
+
+/**
+ Update the second DRHD structure
+
+ @param[in, out] DrhdEnginePtr - A pointer to DRHD structure
+**/
+VOID
+UpdateDrhd2 (
+ IN OUT VOID *DrhdEnginePtr
+ )
+{
+ UINT16 Length;
+ UINTN DeviceScopeNum;
+ UINTN ValidDeviceScopeNum;
+ UINT16 Data16;
+ UINT16 Index;
+ UINT8 Bus;
+ UINT8 Path[2];
+ BOOLEAN NeedRemove;
+ EFI_ACPI_DRHD_ENGINE2_STRUCT *DrhdEngine;
+
+ ///
+ /// Convert DrhdEnginePtr to EFI_ACPI_DRHD_ENGINE2_STRUCT Pointer
+ ///
+ DrhdEngine = (EFI_ACPI_DRHD_ENGINE2_STRUCT *) DrhdEnginePtr;
+
+ Length = DrhdEngine->Length;
+ DeviceScopeNum = (DrhdEngine->Length - EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ Data16 = 0;
+ Bus = 0;
+ ValidDeviceScopeNum = 0;
+ Path[0] = 0;
+ Path[1] = 0;
+
+ AnddTablePreInit ();
+
+ for (Index = 0; Index < DeviceScopeNum; Index++) {
+ NeedRemove = FALSE;
+ /**
+ For HPET and APIC, update device scope if Interrupt remapping is supported. remove device scope
+ if interrupt remapping is not supported.
+ - Index = 0 - IOAPIC
+ - Index = 1 - HPET
+ **/
+ if (mInterruptRemappingSupport) {
+ if (Index == 0) {
+ ///
+ /// Update source id for IoApic's device scope entry
+ ///
+ PchP2sbCfgGet16 (R_PCH_P2SB_IBDF, &Data16);
+ Bus = (UINT8) (Data16 >> 8);
+ if (Bus != 0x00) {
+ Path[0] = (UINT8) ((Data16 & 0xff) >> 3);
+ Path[1] = (UINT8) (Data16 & 0x7);
+ } else {
+ DEBUG ((DEBUG_WARN, "P2SB APIC Bus, Device and Function numbers were not programmed yet or invalid, use hardcoding values instead!\n"));
+ Bus = 0xF0;
+ Path[0] = 0x1F;
+ Path[1] = 0x0;
+ }
+ DrhdEngine->DeviceScope[Index].StartBusNumber = Bus;
+ DrhdEngine->DeviceScope[Index].PciPath[0] = Path[0];
+ DrhdEngine->DeviceScope[Index].PciPath[1] = Path[1];
+ //
+ // Update APIC ID
+ //
+ DrhdEngine->DeviceScope[Index].EnumId = GetIoApicId ();
+ }
+ if (Index == 1) {
+ ///
+ /// Update source id for HPET's device scope entry
+ ///
+ PchP2sbCfgGet16 (R_PCH_P2SB_HBDF, &Data16);
+ Bus = (UINT8) (Data16 >> 8);
+ Path[0] = (UINT8) ((Data16 & 0xFF) >> 3);
+ Path[1] = (UINT8) (Data16 & 0x7);
+ DrhdEngine->DeviceScope[Index].StartBusNumber = Bus;
+ DrhdEngine->DeviceScope[Index].PciPath[0] = Path[0];
+ DrhdEngine->DeviceScope[Index].PciPath[1] = Path[1];
+ }
+ } else {
+ if ((Index == 0) || (Index == 1)) {
+ NeedRemove = TRUE;
+ }
+ }
+
+ switch (Index) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ if (mAnddI2C0Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 3:
+ if (mAnddI2C1Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 4:
+ if (mAnddI2C2Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 5:
+ if (mAnddI2C3Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 6:
+ if (mAnddI2C4Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 7:
+ if (mAnddI2C5Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 8:
+ if (mAnddSpi0Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 9:
+ if (mAnddSpi1Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 10:
+ if (mAnddUa00Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 11:
+ if (mAnddUa01Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ case 12:
+ if (mAnddUa02Needed == FALSE) {
+ NeedRemove = TRUE;
+ }
+ break;
+ default:
+ NeedRemove = TRUE;
+ break;
+ }
+
+ CopyMem (
+ &DrhdEngine->DeviceScope[ValidDeviceScopeNum],
+ &DrhdEngine->DeviceScope[Index],
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE)
+ );
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ } else {
+ ValidDeviceScopeNum++;
+ }
+ }
+ ///
+ /// If no devicescope is left, we set the structure length as 0x00
+ ///
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->Flags == 0x01)) {
+ DrhdEngine->Length = Length;
+ } else {
+ DrhdEngine->Length = 0;
+ }
+}
+
+/**
+ Update the RMRR structure
+
+ @param[in, out] RmrrPtr - A pointer to RMRR structure
+**/
+VOID
+UpdateRmrr (
+ IN OUT VOID *RmrrPtr
+ )
+{
+ UINT16 Length;
+ UINT16 DisableBit;
+ UINTN DeviceScopeNum;
+ UINTN ValidDeviceScopeNum;
+ UINTN Index;
+ BOOLEAN NeedRemove;
+ EFI_ACPI_RMRR_USB_STRUC *Rmrr;
+
+ ///
+ /// To make sure all devicescope can be checked,
+ /// we convert the RmrrPtr to EFI_ACPI_RMRR_USB_STRUC pointer
+ ///
+ Rmrr = (EFI_ACPI_RMRR_USB_STRUC *) RmrrPtr;
+
+ Length = Rmrr->Length;
+ ValidDeviceScopeNum = 0;
+ DeviceScopeNum = (Rmrr->Length - EFI_ACPI_RMRR_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ for (Index = 0; Index < DeviceScopeNum; Index++) {
+ DisableBit = GetFunDisableBit (
+ Rmrr->DeviceScope[Index].PciPath[0],
+ Rmrr->DeviceScope[Index].PciPath[1]
+ );
+ NeedRemove = FALSE;
+ if ((DisableBit == 0xFF) ||
+ ((DisableBit == 0x80) &&
+ (MmioRead32 (MmPciBase (0, Rmrr->DeviceScope[Index].PciPath[0], Rmrr->DeviceScope[Index].PciPath[1]) + 0x00) == 0xFFFFFFFF))
+ ) {
+ NeedRemove = TRUE;
+ }
+ CopyMem (
+ &Rmrr->DeviceScope[ValidDeviceScopeNum],
+ &Rmrr->DeviceScope[Index],
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE)
+ );
+
+ if (Rmrr->RmrLimitAddress == 0x0) {
+ NeedRemove = TRUE;
+ }
+
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ } else {
+ ValidDeviceScopeNum++;
+ }
+ }
+ ///
+ /// If No deviceScope is left, set length as 0x00
+ ///
+ if (Length > EFI_ACPI_RMRR_HEADER_LENGTH) {
+ Rmrr->Length = Length;
+ } else {
+ Rmrr->Length = 0;
+ }
+}
+
+/**
+ Update the DMAR table
+
+ @param[in, out] TableHeader - The table to be set
+ @param[in, out] Version - Version to publish
+**/
+VOID
+DmarTableUpdate (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+{
+ EFI_ACPI_DMAR_TABLE *DmarTable;
+ EFI_ACPI_DMAR_TABLE TempDmarTable;
+ UINTN Offset;
+ UINTN StructureLen;
+ UINTN McD0BaseAddress;
+ UINT32 MchBar;
+ UINT16 IgdMode;
+ UINT16 GttMode;
+ UINT32 IgdMemSize;
+ UINT32 GttMemSize;
+ EFI_STATUS Status;
+ MISC_DXE_CONFIG *MiscDxeConfig;
+ CPU_GENERATION CpuGeneration;
+ UINT64 OemTableId;
+
+ IgdMemSize = 0;
+ GttMemSize = 0;
+ DmarTable = (EFI_ACPI_DMAR_TABLE *) TableHeader;
+ CpuGeneration = GetCpuGeneration ();
+ //
+ // The Default OEM Table ID is "KBL "
+ //
+ OemTableId = KBL_OEM_TABLE_ID;
+
+ Status = GetConfigBlock ((VOID *) mSaPolicy, &gMiscDxeConfigGuid, (VOID *)&MiscDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Set INTR_REMAP bit (BIT 0) if interrupt remapping is supported
+ ///
+ if (mInterruptRemappingSupport) {
+ DmarTable->Flags |= BIT0;
+ }
+
+ if (SaConfigHob->VtdData.X2ApicOptOut == 1) {
+ DmarTable->Flags |= BIT1;
+ } else {
+ DmarTable->Flags &= 0xFD;
+ }
+
+ ///
+ /// Get OemId
+ ///
+ CopyMem (DmarTable->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (DmarTable->Header.OemId));
+
+ if (CpuGeneration == EnumSklCpu) {
+ //
+ // Use "SKL " as OEM Table ID if the CpuGeneration is SKL
+ //
+ OemTableId = SKL_OEM_TABLE_ID;
+ }
+ //
+ // Update OEM Table ID
+ //
+ DmarTable->Header.OemTableId = OemTableId;
+
+ ///
+ /// Calculate IGD memsize
+ ///
+ McD0BaseAddress = MmPciBase (SA_MC_BUS, 0, 0);
+ MchBar = (UINT32) MmioRead64 (McD0BaseAddress + R_SA_MCHBAR) & ~BIT0;
+ IgdMode = ((MmioRead16 (McD0BaseAddress + R_SA_GGC) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
+ if (IgdMode < 0xF0) {
+ IgdMemSize = IgdMode * 32 * (1024) * (1024);
+ } else {
+ IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+ }
+ ///
+ /// Calculate GTT mem size
+ ///
+ GttMemSize = 0;
+ GttMode = (MmioRead16 (McD0BaseAddress + R_SA_GGC) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
+ if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
+ GttMemSize = (1 << GttMode) * (1024) * (1024);
+ }
+
+ DmarTable->RmrrIgd.RmrBaseAddress = (MmioRead32 (McD0BaseAddress + R_SA_TOLUD) & ~(0x01)) - IgdMemSize - GttMemSize;
+ DmarTable->RmrrIgd.RmrLimitAddress = DmarTable->RmrrIgd.RmrBaseAddress + IgdMemSize + GttMemSize - 1;
+ DEBUG ((DEBUG_INFO, "RMRR Base address IGD %016lX\n", DmarTable->RmrrIgd.RmrBaseAddress));
+ DEBUG ((DEBUG_INFO, "RMRR Limit address IGD %016lX\n", DmarTable->RmrrIgd.RmrLimitAddress));
+
+ DmarTable->RmrrUsb.RmrBaseAddress = MiscDxeConfig->RmrrUsbBaseAddress[0];
+ DmarTable->RmrrUsb.RmrLimitAddress = MiscDxeConfig->RmrrUsbBaseAddress[1];
+
+ ///
+ /// Convert to 4KB alignment.
+ ///
+ if (DmarTable->RmrrUsb.RmrLimitAddress != 0x0) {
+ DmarTable->RmrrUsb.RmrBaseAddress &= (EFI_PHYSICAL_ADDRESS) ~0xFFF;
+ DmarTable->RmrrUsb.RmrLimitAddress &= (EFI_PHYSICAL_ADDRESS) ~0xFFF;
+ DmarTable->RmrrUsb.RmrLimitAddress += 0x1000-1;
+ }
+
+ DEBUG ((DEBUG_INFO, "RMRR Base address USB %016lX\n", DmarTable->RmrrUsb.RmrBaseAddress));
+ DEBUG ((DEBUG_INFO, "RMRR Limit address USB %016lX\n", DmarTable->RmrrUsb.RmrLimitAddress));
+
+ if (DmarTable->RmrrUsb.RmrBaseAddress == 0) {
+ DEBUG ((DEBUG_WARN, "WARNING: RmrrUsb.RmrBaseAddress is 0.\n"));
+ }
+ ///
+ /// Update DRHD structures of DmarTable
+ ///
+ DmarTable->DrhdEngine1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
+ DmarTable->DrhdEngine2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+
+ DEBUG ((DEBUG_INFO, "VTD base address1 %x\n", DmarTable->DrhdEngine1.RegisterBaseAddress));
+ DEBUG ((DEBUG_INFO, "VTD base address2 %x\n", DmarTable->DrhdEngine2.RegisterBaseAddress));
+ ///
+ /// copy DmarTable to TempDmarTable to be processed
+ ///
+ CopyMem (&TempDmarTable, DmarTable, sizeof (EFI_ACPI_DMAR_TABLE));
+
+ UpdateDrhd (&TempDmarTable.DrhdEngine1);
+ UpdateDrhd2 (&TempDmarTable.DrhdEngine2);
+
+ ///
+ /// Update RMRR structures of temp DMAR table
+ ///
+ UpdateRmrr ((VOID *) &TempDmarTable.RmrrUsb);
+ UpdateRmrr ((VOID *) &TempDmarTable.RmrrIgd);
+
+ ///
+ /// Remove unused device scope or entire DRHD structures
+ ///
+ Offset = (UINTN) (&TempDmarTable.DrhdEngine1);
+ if (TempDmarTable.DrhdEngine1.Length != 0) {
+ Offset += TempDmarTable.DrhdEngine1.Length;
+ }
+ if (TempDmarTable.DrhdEngine2.Length != 0) {
+ StructureLen = TempDmarTable.DrhdEngine2.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.DrhdEngine2, TempDmarTable.DrhdEngine2.Length);
+ Offset += StructureLen;
+ }
+ ///
+ /// Remove unused device scope or entire RMRR structures
+ ///
+ if (TempDmarTable.RmrrUsb.Length != 0) {
+ StructureLen = TempDmarTable.RmrrUsb.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.RmrrUsb, TempDmarTable.RmrrUsb.Length);
+ Offset += StructureLen;
+ }
+ if (TempDmarTable.RmrrIgd.Length != 0) {
+ StructureLen = TempDmarTable.RmrrIgd.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.RmrrIgd, TempDmarTable.RmrrIgd.Length);
+ Offset += StructureLen;
+ }
+
+ ///
+ /// Include necessary ANDD structures for SPT
+ ///
+ if (mAnddI2C0Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddI2C0.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C0, TempDmarTable.AnddI2C0.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddI2C1Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddI2C1.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C1, TempDmarTable.AnddI2C1.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddI2C2Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddI2C2.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C2, TempDmarTable.AnddI2C2.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddI2C3Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddI2C3.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C3, TempDmarTable.AnddI2C3.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddI2C4Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddI2C4.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C4, TempDmarTable.AnddI2C4.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddI2C5Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddI2C5.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C5, TempDmarTable.AnddI2C5.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddSpi0Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddSpi0.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddSpi0, TempDmarTable.AnddSpi0.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddSpi1Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddSpi1.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddSpi1, TempDmarTable.AnddSpi1.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddUa00Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddUa00.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddUa00, TempDmarTable.AnddUa00.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddUa01Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddUa01.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddUa01, TempDmarTable.AnddUa01.Length);
+ Offset += StructureLen;
+ }
+ if (mAnddUa02Needed == TRUE) {
+ StructureLen = TempDmarTable.AnddUa02.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddUa02, TempDmarTable.AnddUa02.Length);
+ Offset += StructureLen;
+ }
+
+ Offset = Offset - (UINTN) &TempDmarTable;
+ ///
+ /// Re-calculate DMAR table check sum
+ ///
+ TempDmarTable.Header.Checksum = (UINT8) (TempDmarTable.Header.Checksum + TempDmarTable.Header.Length - Offset);
+ ///
+ /// Set DMAR table length
+ ///
+ TempDmarTable.Header.Length = (UINT32) Offset;
+ ///
+ /// Replace DMAR table with rebuilt table TempDmarTable
+ ///
+ CopyMem ((VOID *) DmarTable, (VOID *) &TempDmarTable, TempDmarTable.Header.Length);
+}
+
+/**
+ EndOfDxe routine for update DMAR
+**/
+VOID
+UpdateDmarEndOfDxe (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+ INTN Instance;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN AcpiTableHandle;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_ACPI_DESCRIPTION_HEADER *VtdAcpiTable;
+ STATIC BOOLEAN Triggered = FALSE;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ if (Triggered) {
+ return;
+ }
+
+ Triggered = TRUE;
+
+ FwVol = NULL;
+ AcpiTable = NULL;
+ VtdAcpiTable = NULL;
+
+ ///
+ /// Locate PCH Policy HOB and PCH series to support feature enabling/disabling
+ ///
+ //
+ // Get PCH Config HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gPchConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mPchConfigHob = GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ mPchSeries = GetPchSeries ();
+
+ ///
+ /// Locate ACPI support protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+
+ ///
+ /// Locate protocol.
+ /// There is little chance we can't find an FV protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Looking for FV with ACPI storage file
+ ///
+ for (i = 0; i < NumberOfHandles; i++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &gSaAcpiTableStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ ///
+ /// If we found it, then we are done
+ ///
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+ ///
+ /// Our exit status is determined by the success of the previous operations
+ /// If the protocol was found, Instance already points to it.
+ ///
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol);
+ if (FwVol == NULL) {
+ return;
+ }
+ ///
+ /// By default, a table belongs in all ACPI table versions published.
+ ///
+ Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+
+ ///
+ /// Read tables from the storage file.
+ ///
+ Instance = 0;
+ CurrentTable = NULL;
+
+ while (Status == EFI_SUCCESS) {
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gSaAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID **) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Check the Signature ID to modify the table
+ ///
+ switch (((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Signature) {
+
+ case EFI_ACPI_VTD_DMAR_TABLE_SIGNATURE:
+ VtdAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ DmarTableUpdate (VtdAcpiTable, &Version);
+ break;
+
+ default:
+ break;
+ }
+ ///
+ /// Increment the instance
+ ///
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+ ///
+ /// Update the VTD table in the ACPI tables.
+ ///
+ AcpiTableHandle = 0;
+ if (VtdAcpiTable != NULL) {
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ VtdAcpiTable,
+ VtdAcpiTable->Length,
+ &AcpiTableHandle
+ );
+ FreePool (VtdAcpiTable);
+ }
+}
+
+/**
+ Locate the VT-d ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @param[in] SaPolicy - SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - Vtd initialization complete
+ @exception EFI_UNSUPPORTED - Vtd is not enabled by policy
+**/
+EFI_STATUS
+VtdInit (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ UINTN McD0BaseAddress;
+
+ mInterruptRemappingSupport = FALSE;
+ SaConfigHob = NULL;
+ SaConfigHob = GetFirstGuidHob (&gSaConfigHobGuid);
+ if (SaConfigHob != NULL) {
+ mInterruptRemappingSupport = SaConfigHob->VtdData.InterruptRemappingSupport;
+ }
+
+ McD0BaseAddress = MmPciBase (SA_MC_BUS, 0, 0);
+ mSaPolicy = SaPolicy;
+
+ if (((SaConfigHob != NULL) && (SaConfigHob->VtdData.VtdDisable)) || (MmioRead32 (McD0BaseAddress + R_SA_MC_CAPID0_A_OFFSET) & BIT23)) {
+ DEBUG ((DEBUG_WARN, "VTd disabled or no capability!\n"));
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Check SA supports VTD and VTD is enabled in setup menu
+ ///
+ DEBUG ((DEBUG_INFO, "VTd enabled\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.h
new file mode 100644
index 0000000000..fc84a7c41e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SaInit/Dxe/VTd.h
@@ -0,0 +1,61 @@
+/** @file
+ This code provides a initialization of intel VT-d (Virtualization Technology for Directed I/O).
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _VT_D_H_
+#define _VT_D_H_
+
+///
+/// Include files
+///
+#include <DmaRemappingTable.h>
+#include <SaAccess.h>
+#include <PchAccess.h>
+#include <Uefi.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/AcpiTable.h>
+#include <Library/MmPciLib.h>
+#include <Protocol/SaPolicy.h>
+#include <SiConfigHob.h>
+#include <PchConfigHob.h>
+#include <CpuRegs.h>
+#include <Library/CpuPlatformLib.h>
+
+
+#define VTD_ECAP_REG 0x10
+#define IR BIT3
+
+#define KBL_OEM_TABLE_ID 0x204C424B ///< "KBL "
+#define SKL_OEM_TABLE_ID 0x204C4B53 ///< "SKL "
+
+/**
+ Locate the VT-d ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @param[in] SaPolicy SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - Vtd initialization complete
+ @retval Other - No Vtd function initiated
+**/
+EFI_STATUS
+VtdInit (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ );
+
+/**
+ EndOfDxe routine for update DMAR
+**/
+VOID
+UpdateDmarEndOfDxe (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccess.inf b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccess.inf
new file mode 100644
index 0000000000..150716529c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccess.inf
@@ -0,0 +1,55 @@
+## @file
+# Component description file for the SmmAccess module
+#
+# {1323C7F8-DAD5-4126-A54B-7A05FBF4151}
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SmmAccess
+FILE_GUID = 1323C7F8-DAD5-4126-A54B-7A05FBF41515
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = SmmAccessDriverEntryPoint
+
+
+[LibraryClasses]
+UefiDriverEntryPoint
+BaseLib
+BaseMemoryLib
+DebugLib
+HobLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SmmAccessDriver.h
+SmmAccessDriver.c
+
+
+[Protocols]
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gEfiSmmAccess2ProtocolGuid ## PRODUCES
+
+
+[Guids]
+gEfiSmmPeiSmramMemoryReserveGuid
+
+
+[Depex]
+gEfiPciRootBridgeIoProtocolGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.c b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.c
new file mode 100644
index 0000000000..3e8fd96484
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.c
@@ -0,0 +1,434 @@
+/** @file
+ This is the driver that publishes the SMM Access Protocol
+ instance for System Agent.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "SmmAccessDriver.h"
+
+static SMM_ACCESS_PRIVATE_DATA mSmmAccess;
+
+
+/**
+ This is the standard EFI driver point that
+ installs an SMM Access Protocol
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - Protocol was installed successfully
+ @exception EFI_UNSUPPORTED - Protocol was not installed
+ @retval EFI_NOT_FOUND - Protocol can't be found.
+ @retval EFI_OUT_OF_RESOURCES - Protocol does not have enough resources to initialize the driver.
+**/
+EFI_STATUS
+EFIAPI
+SmmAccessDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINTN Index;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+ EFI_PEI_HOB_POINTERS *Hob;
+
+ ///
+ /// --cr-- INITIALIZE_SCRIPT (ImageHandle, SystemTable);
+ ///
+ /// Initialize Global variables
+ ///
+ ZeroMem (&mSmmAccess, sizeof (mSmmAccess));
+
+ Status = gBS->LocateProtocol (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ (VOID **) &PciRootBridgeIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Could not locate PCI Root Bridge IO Protocol\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ mSmmAccess.Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;
+ mSmmAccess.Handle = NULL;
+ mSmmAccess.PciRootBridgeIo = PciRootBridgeIo;
+
+ ///
+ /// Get Hob list
+ ///
+ Hob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+ if (Hob == NULL) {
+ DEBUG ((DEBUG_ERROR, "SmramMemoryReserve HOB not found\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ DescriptorBlock = (VOID *) ((UINT8 *) Hob + sizeof (EFI_HOB_GUID_TYPE));
+
+ ///
+ /// Alloc space for mSmmAccess.SmramDesc
+ ///
+ mSmmAccess.SmramDesc = AllocateZeroPool ((DescriptorBlock->NumberOfSmmReservedRegions) * sizeof (EFI_SMRAM_DESCRIPTOR));
+ if (mSmmAccess.SmramDesc == NULL) {
+ DEBUG ((DEBUG_ERROR, "Alloc mSmmAccess.SmramDesc fail.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((DEBUG_INFO, "Alloc mSmmAccess.SmramDesc success.\n"));
+
+ ///
+ /// Use the HOB to publish SMRAM capabilities
+ ///
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {
+ mSmmAccess.SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;
+ mSmmAccess.SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;
+ mSmmAccess.SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;
+ mSmmAccess.SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;
+ }
+
+ mSmmAccess.NumberRegions = Index;
+ mSmmAccess.SmmAccess.Open = Open;
+ mSmmAccess.SmmAccess.Close = Close;
+ mSmmAccess.SmmAccess.Lock = Lock;
+ mSmmAccess.SmmAccess.GetCapabilities = GetCapabilities;
+ mSmmAccess.SmmAccess.LockState = FALSE;
+ mSmmAccess.SmmAccess.OpenState = FALSE;
+
+ ///
+ /// Install our protocol interfaces on the device's handle
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mSmmAccess.Handle,
+ &gEfiSmmAccess2ProtocolGuid,
+ &mSmmAccess.SmmAccess,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "InstallMultipleProtocolInterfaces returned %r\n", Status));
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine accepts a request to "open" a region of SMRAM. The
+ region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+ The use of "open" means that the memory is visible from all boot-service
+ and SMM agents.
+
+ @param[in] This - Pointer to the SMM Access Interface.
+
+ @retval EFI_SUCCESS - The region was successfully opened.
+ @retval EFI_DEVICE_ERROR - The region could not be opened because locked by
+ chipset.
+ @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+**/
+EFI_STATUS
+EFIAPI
+Open (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ UINT64 Address;
+ UINT8 SmramControl;
+ UINTN DescriptorIndex;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+ for (DescriptorIndex = 0; DescriptorIndex < SmmAccess->NumberRegions; DescriptorIndex++) {
+ if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
+ DEBUG ((DEBUG_WARN, "Cannot open a locked SMRAM region\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ ///
+ /// BEGIN CHIPSET SPECIFIC CODE
+ ///
+ ///
+ /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit)
+ ///
+ Address = EFI_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC);
+
+ Status = SmmAccess->PciRootBridgeIo->Pci.Read (
+ SmmAccess->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &SmramControl
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "SmmAccess->PciRootBridgeIo->Pci.Read returned %r\n", Status));
+ return Status;
+ }
+ ///
+ /// Is SMRAM locked?
+ ///
+ for (DescriptorIndex = 0; DescriptorIndex < SmmAccess->NumberRegions; DescriptorIndex++) {
+ if ((SmramControl & B_SA_SMRAMC_D_LCK_MASK) != 0) {
+ ///
+ /// Cannot Open a locked region
+ ///
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
+ DEBUG ((DEBUG_WARN, "Cannot open a locked SMRAM region\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ ///
+ /// Open SMRAM region
+ ///
+ SmramControl |= B_SA_SMRAMC_D_OPEN_MASK;
+ SmramControl &= ~(B_SA_SMRAMC_D_CLS_MASK);
+
+ Status = SmmAccess->PciRootBridgeIo->Pci.Write (
+ SmmAccess->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &SmramControl
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "SmmAccess->PciRootBridgeIo->Pci.Write returned %r\n", Status));
+ return Status;
+ }
+ ///
+ /// END CHIPSET SPECIFIC CODE
+ ///
+ for (DescriptorIndex = 0; DescriptorIndex < SmmAccess->NumberRegions; DescriptorIndex++) {
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState &= (UINT64) ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (UINT64) EFI_SMRAM_OPEN;
+ }
+ SmmAccess->SmmAccess.OpenState = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine accepts a request to "close" a region of SMRAM. The
+ region could be legacy AB or TSEG near top of physical memory.
+ The use of "close" means that the memory is only visible from SMM agents,
+ not from BS or RT code.
+
+ @param[in] This - Pointer to the SMM Access Interface.
+
+ @retval EFI_SUCCESS - The region was successfully closed.
+ @retval EFI_DEVICE_ERROR - The region could not be closed because locked by chipset.
+ @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+**/
+EFI_STATUS
+EFIAPI
+Close (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ UINT64 Address;
+ BOOLEAN OpenState;
+ UINT8 Index;
+ UINT8 SmramControl;
+ UINTN DescriptorIndex;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ for (DescriptorIndex = 0; DescriptorIndex < SmmAccess->NumberRegions; DescriptorIndex++) {
+ if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
+ DEBUG ((DEBUG_WARN, "Cannot close a locked SMRAM region\n"));
+ continue;
+ }
+
+ ///
+ /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit)
+ ///
+ Address = EFI_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC);
+
+ Status = SmmAccess->PciRootBridgeIo->Pci.Read (
+ SmmAccess->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &SmramControl
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "SmmAccess->PciRootBridgeIo->Pci.Read returned %r\n", Status));
+ return Status;
+ }
+ ///
+ /// Is SMRAM locked?
+ ///
+ if ((SmramControl & B_SA_SMRAMC_D_LCK_MASK) != 0) {
+ ///
+ /// Cannot Close a locked region
+ ///
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
+ DEBUG ((DEBUG_WARN, "Cannot close a locked SMRAM region\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Close SMRAM region
+ ///
+ SmramControl &= ~(B_SA_SMRAMC_D_OPEN_MASK);
+
+ Status = SmmAccess->PciRootBridgeIo->Pci.Write (
+ SmmAccess->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &SmramControl
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "SmmAccess->PciRootBridgeIo->Pci.Write returned %r\n", Status));
+ return Status;
+ }
+ ///
+ /// END CHIPSET SPECIFIC CODE
+ ///
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState &= (UINT64) ~EFI_SMRAM_OPEN;
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (UINT64) (EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+ }
+
+ ///
+ /// Find out if any regions are still open
+ ///
+ OpenState = FALSE;
+ for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {
+ if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {
+ OpenState = TRUE;
+ }
+ }
+
+ SmmAccess->SmmAccess.OpenState = OpenState;
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine accepts a request to "lock" SMRAM. The
+ region could be legacy AB or TSEG near top of physical memory.
+ The use of "lock" means that the memory can no longer be opened
+ to BS state..
+
+ @param[in] This - Pointer to the SMM Access Interface.
+
+ @retval EFI_SUCCESS - The region was successfully locked.
+ @retval EFI_DEVICE_ERROR - The region could not be locked because at least
+ one range is still open.
+ @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+**/
+EFI_STATUS
+EFIAPI
+Lock (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ UINT64 Address;
+ UINT8 SmramControl;
+ UINTN DescriptorIndex;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ if (SmmAccess->SmmAccess.OpenState) {
+ DEBUG ((DEBUG_WARN, "Cannot lock SMRAM when SMRAM regions are still open\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ for (DescriptorIndex = 0; DescriptorIndex < SmmAccess->NumberRegions; DescriptorIndex++) {
+ SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
+ }
+ SmmAccess->SmmAccess.LockState = TRUE;
+
+ ///
+ /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit)
+ ///
+ Address = EFI_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC);
+
+ Status = SmmAccess->PciRootBridgeIo->Pci.Read (
+ SmmAccess->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &SmramControl
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "SmmAccess->PciRootBridgeIo->Pci.Read returned %r\n", Status));
+ return Status;
+ }
+ ///
+ /// Lock the SMRAM
+ ///
+ SmramControl |= B_SA_SMRAMC_D_LCK_MASK;
+
+ Status = SmmAccess->PciRootBridgeIo->Pci.Write (
+ SmmAccess->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &SmramControl
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "SmmAccess->PciRootBridgeIo->Pci.Write returned %r\n", Status));
+ return Status;
+ }
+ ///
+ /// END CHIPSET SPECIFIC CODE
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine services a user request to discover the SMRAM
+ capabilities of this platform. This will report the possible
+ ranges that are possible for SMRAM access, based upon the
+ memory controller capabilities.
+
+ @param[in] This - Pointer to the SMRAM Access Interface.
+ @param[in] SmramMapSize - Pointer to the variable containing size of the
+ buffer to contain the description information.
+ @param[in] SmramMap - Buffer containing the data describing the Smram
+ region descriptors.
+
+ @retval EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
+ @retval EFI_SUCCESS - The user provided a sufficiently-sized buffer.
+**/
+EFI_STATUS
+EFIAPI
+GetCapabilities (
+ IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,
+ IN OUT UINTN *SmramMapSize,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+ )
+{
+ EFI_STATUS Status;
+ SMM_ACCESS_PRIVATE_DATA *SmmAccess;
+ UINTN NecessaryBufferSize;
+
+ SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+ NecessaryBufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
+
+ if (*SmramMapSize < NecessaryBufferSize) {
+ DEBUG ((DEBUG_WARN, "SMRAM Map Buffer too small\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else {
+ CopyMem (SmramMap, SmmAccess->SmramDesc, NecessaryBufferSize);
+ Status = EFI_SUCCESS;
+ }
+
+ *SmramMapSize = NecessaryBufferSize;
+
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.h b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.h
new file mode 100644
index 0000000000..69e9e89b24
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.h
@@ -0,0 +1,171 @@
+/** @file
+ Header file for SMM Access Driver.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SMM_ACCESS_DRIVER_H_
+#define _SMM_ACCESS_DRIVER_H_
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Guid/SmramMemoryReserve.h>
+#include <Protocol/SmmAccess2.h>
+#include <IndustryStandard/Pci22.h>
+#include <SaAccess.h>
+
+#define SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('4', '5', 's', 'a')
+
+///
+/// Private data
+///
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_ACCESS2_PROTOCOL SmmAccess;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ ///
+ /// Local Data for SMM Access interface goes here
+ ///
+ UINTN NumberRegions;
+ EFI_SMRAM_DESCRIPTOR *SmramDesc;
+} SMM_ACCESS_PRIVATE_DATA;
+
+#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ SMM_ACCESS_PRIVATE_DATA, \
+ SmmAccess, \
+ SMM_ACCESS_PRIVATE_DATA_SIGNATURE \
+ )
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+/**
+ <b>SMM Access Driver Entry Point</b>
+ This driver installs an SMM Access Protocol
+ - <b>Introduction</b> \n
+ This module publishes the SMM access protocol. The protocol is used by the SMM Base driver to access the SMRAM region when the processor is not in SMM.
+ The SMM Base driver uses the services provided by the SMM access protocol to open SMRAM during post and copy the SMM handler.
+ SMM access protocol is also used to close the SMRAM region once the copying is done.
+ Finally, the SMM access protocol provides services to "Lock" the SMRAM region.
+ Please refer the SMM Protocols section in the attached SMM CIS Specification version 0.9 for further details.
+ This driver is required if SMM is supported. Proper configuration of SMM registers is recommended even if SMM is not supported.
+
+ - @pre
+ - _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+
+ - @result
+ Publishes the _EFI_SMM_ACCESS_PROTOCOL: Documented in the System Management Mode Core Interface Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+
+ - <b>Porting Recommendations</b> \n
+ No modification of this module is recommended. Any modification should be done in compliance with the _EFI_SMM_ACCESS_PROTOCOL protocol definition.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - Protocol was installed successfully
+ @exception EFI_UNSUPPORTED - Protocol was not installed
+**/
+EFI_STATUS
+EFIAPI
+SmmAccessDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This routine accepts a request to "open" a region of SMRAM. The
+ region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+ The use of "open" means that the memory is visible from all boot-service
+ and SMM agents.
+
+ @param[in] This - Pointer to the SMM Access Interface.
+
+ @retval EFI_SUCCESS - The region was successfully opened.
+ @retval EFI_DEVICE_ERROR - The region could not be opened because locked by
+ chipset.
+ @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+**/
+EFI_STATUS
+EFIAPI
+Open (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ );
+
+/**
+ This routine accepts a request to "close" a region of SMRAM. The
+ region could be legacy AB or TSEG near top of physical memory.
+ The use of "close" means that the memory is only visible from SMM agents,
+ not from BS or RT code.
+
+ @param[in] This - Pointer to the SMM Access Interface.
+
+ @retval EFI_SUCCESS - The region was successfully closed.
+ @retval EFI_DEVICE_ERROR - The region could not be closed because locked by
+ chipset.
+ @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+**/
+EFI_STATUS
+EFIAPI
+Close (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ );
+
+/**
+ This routine accepts a request to "lock" SMRAM. The
+ region could be legacy AB or TSEG near top of physical memory.
+ The use of "lock" means that the memory can no longer be opened
+ to BS state..
+
+ @param[in] This - Pointer to the SMM Access Interface.
+
+ @retval EFI_SUCCESS - The region was successfully locked.
+ @retval EFI_DEVICE_ERROR - The region could not be locked because at least
+ one range is still open.
+ @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
+**/
+EFI_STATUS
+EFIAPI
+Lock (
+ IN EFI_SMM_ACCESS2_PROTOCOL *This
+ );
+
+/**
+ This routine services a user request to discover the SMRAM
+ capabilities of this platform. This will report the possible
+ ranges that are possible for SMRAM access, based upon the
+ memory controller capabilities.
+
+ @param[in] This - Pointer to the SMRAM Access Interface.
+ @param[in] SmramMapSize - Pointer to the variable containing size of the
+ buffer to contain the description information.
+ @param[in] SmramMap - Buffer containing the data describing the Smram
+ region descriptors.
+
+ @retval EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
+ @retval EFI_SUCCESS - The user provided a sufficiently-sized buffer.
+**/
+EFI_STATUS
+EFIAPI
+GetCapabilities (
+ IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,
+ IN OUT UINTN *SmramMapSize,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+ );
+#endif