summaryrefslogtreecommitdiff
path: root/Vlv2TbltDevicePkg/PlatformSmm
diff options
context:
space:
mode:
authorDavid Wei <david.wei@intel.com>2015-01-12 09:37:20 +0000
committerzwei4 <zwei4@Edk2>2015-01-12 09:37:20 +0000
commit3cbfba02fef9dae07a041fdbf2e89611d72d6f90 (patch)
tree0b3bf0783124d38a191e09736492c0141aa36c15 /Vlv2TbltDevicePkg/PlatformSmm
parent6f785cfcc304c48ec04e542ee429df95e7b51bc5 (diff)
Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to
https://svn.code.sf.net/p/edk2/code/trunk/edk2/, which are for MinnowBoard MAX open source project. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: David Wei <david.wei@intel.com> Reviewed-by: Mike Wu <mike.wu@intel.com> Reviewed-by: Hot Tian <hot.tian@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16599 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'Vlv2TbltDevicePkg/PlatformSmm')
-rw-r--r--Vlv2TbltDevicePkg/PlatformSmm/Platform.c977
-rw-r--r--Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf98
-rw-r--r--Vlv2TbltDevicePkg/PlatformSmm/S3Save.c382
-rw-r--r--Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h245
-rw-r--r--Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c257
-rw-r--r--Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h55
6 files changed, 2014 insertions, 0 deletions
diff --git a/Vlv2TbltDevicePkg/PlatformSmm/Platform.c b/Vlv2TbltDevicePkg/PlatformSmm/Platform.c
new file mode 100644
index 000000000..d8bfeb437
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformSmm/Platform.c
@@ -0,0 +1,977 @@
+/** @file
+
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ Platform.c
+
+Abstract:
+
+ This is a generic template for a child of the IchSmm driver.
+
+
+--*/
+
+#include "SmmPlatform.h"
+#include <Protocol/CpuIo2.h>
+
+
+//
+// Local variables
+//
+typedef struct {
+ UINT8 Device;
+ UINT8 Function;
+} EFI_PCI_BUS_MASTER;
+
+EFI_PCI_BUS_MASTER mPciBm[] = {
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 },
+ { PCI_DEVICE_NUMBER_PCH_USB, PCI_FUNCTION_NUMBER_PCH_EHCI }
+};
+
+
+UINT16 mAcpiBaseAddr;
+SYSTEM_CONFIGURATION mSystemConfiguration;
+EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
+EFI_GLOBAL_NVS_AREA_PROTOCOL *mGlobalNvsAreaPtr;
+
+UINT16 mPM1_SaveState16;
+UINT32 mGPE_SaveState32;
+
+BOOLEAN mSetSmmVariableProtocolSmiAllowed = TRUE;
+
+
+//
+// Variables. Need to initialize this from Setup
+//
+BOOLEAN mWakeOnLanS5Variable;
+BOOLEAN mWakeOnRtcVariable;
+UINT8 mWakeupDay;
+UINT8 mWakeupHour;
+UINT8 mWakeupMinute;
+UINT8 mWakeupSecond;
+
+//
+// Use an enum. 0 is Stay Off, 1 is Last State, 2 is Stay On
+//
+UINT8 mAcLossVariable;
+
+
+static
+UINT8 mTco1Sources[] = {
+ IchnNmi
+};
+
+UINTN
+DevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+VOID
+S4S5ProgClock();
+
+EFI_STATUS
+InitRuntimeScriptTable (
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+S5SleepWakeOnRtcCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ );
+
+
+VOID
+EnableS5WakeOnRtc();
+
+UINT8
+HexToBcd(
+ UINT8 HexValue
+ );
+
+UINT8
+BcdToHex(
+ IN UINT8 BcdValue
+ );
+
+
+VOID
+CpuSmmSxWorkAround(
+ );
+
+/**
+ Initializes the SMM Handler Driver
+
+ @param ImageHandle
+ @param SystemTable
+
+ @retval None
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatformSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_HANDLE Handle;
+ EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT PowerButtonContext;
+ EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL *PowerButtonDispatch;
+ EFI_SMM_ICHN_DISPATCH_CONTEXT IchnContext;
+ EFI_SMM_ICHN_DISPATCH_PROTOCOL *IchnDispatch;
+ EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatch;
+ EFI_SMM_SX_DISPATCH_CONTEXT EntryDispatchContext;
+ EFI_SMM_SW_DISPATCH_PROTOCOL *SwDispatch;
+ EFI_SMM_SW_DISPATCH_CONTEXT SwContext;
+ UINTN VarSize;
+ EFI_BOOT_MODE BootMode;
+
+ Handle = NULL;
+
+ //
+ // Locate the Global NVS Protocol.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiGlobalNvsAreaProtocolGuid,
+ NULL,
+ (void **)&mGlobalNvsAreaPtr
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Get the ACPI Base Address
+ //
+
+ mAcpiBaseAddr = PchLpcPciCfg16( R_PCH_LPC_ACPI_BASE ) & B_PCH_LPC_ACPI_BASE_BAR;
+
+ VarSize = sizeof(SYSTEM_CONFIGURATION);
+ Status = SystemTable->RuntimeServices->GetVariable(
+ L"Setup",
+ &gEfiSetupVariableGuid,
+ NULL,
+ &VarSize,
+ &mSystemConfiguration
+ );
+ if (!EFI_ERROR(Status)) {
+ mAcLossVariable = mSystemConfiguration.StateAfterG3;
+
+ //
+ // If LAN is disabled, WOL function should be disabled too.
+ //
+ if (mSystemConfiguration.Lan == 0x01){
+ mWakeOnLanS5Variable = mSystemConfiguration.WakeOnLanS5;
+ } else {
+ mWakeOnLanS5Variable = FALSE;
+ }
+
+ mWakeOnRtcVariable = mSystemConfiguration.WakeOnRtcS5;
+ }
+
+ BootMode = GetBootModeHob ();
+
+ //
+ // Get the Power Button protocol
+ //
+ Status = gBS->LocateProtocol(
+ &gEfiSmmPowerButtonDispatchProtocolGuid,
+ NULL,
+ (void **)&PowerButtonDispatch
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {
+ //
+ // Register for the power button event
+ //
+ PowerButtonContext.Phase = PowerButtonEntry;
+ Status = PowerButtonDispatch->Register(
+ PowerButtonDispatch,
+ PowerButtonCallback,
+ &PowerButtonContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR(Status);
+ }
+ //
+ // Get the Sx dispatch protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiSmmSxDispatchProtocolGuid,
+ NULL,
+ (void **)&SxDispatch
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register entry phase call back function
+ //
+ EntryDispatchContext.Type = SxS3;
+ EntryDispatchContext.Phase = SxEntry;
+
+ Status = SxDispatch->Register (
+ SxDispatch,
+ (EFI_SMM_SX_DISPATCH)SxSleepEntryCallBack,
+ &EntryDispatchContext,
+ &Handle
+ );
+
+
+ EntryDispatchContext.Type = SxS4;
+
+ Status = SxDispatch->Register (
+ SxDispatch,
+ S4S5CallBack,
+ &EntryDispatchContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR(Status);
+
+
+ EntryDispatchContext.Type = SxS5;
+
+ Status = SxDispatch->Register (
+ SxDispatch,
+ S4S5CallBack,
+ &EntryDispatchContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ Status = SxDispatch->Register (
+ SxDispatch,
+ S5SleepAcLossCallBack,
+ &EntryDispatchContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Get the Sw dispatch protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiSmmSwDispatchProtocolGuid,
+ NULL,
+ (void **)&SwDispatch
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register ACPI enable handler
+ //
+ SwContext.SwSmiInputValue = ACPI_ENABLE;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ EnableAcpiCallback,
+ &SwContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register ACPI disable handler
+ //
+ SwContext.SwSmiInputValue = ACPI_DISABLE;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ DisableAcpiCallback,
+ &SwContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR(Status);
+
+
+ //
+ // Register for SmmReadyToBootCallback
+ //
+ SwContext.SwSmiInputValue = SMI_SET_SMMVARIABLE_PROTOCOL;
+ Status = SwDispatch->Register(
+ SwDispatch,
+ SmmReadyToBootCallback,
+ &SwContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Get the ICHn protocol
+ //
+ Status = gBS->LocateProtocol(
+ &gEfiSmmIchnDispatchProtocolGuid,
+ NULL,
+ (void **)&IchnDispatch
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register for the events that may happen that we do not care.
+ // This is true for SMI related to TCO since TCO is enabled by BIOS WP
+ //
+ for (Index = 0; Index < sizeof(mTco1Sources)/sizeof(UINT8); Index++) {
+ IchnContext.Type = mTco1Sources[Index];
+ Status = IchnDispatch->Register(
+ IchnDispatch,
+ (EFI_SMM_ICHN_DISPATCH)DummyTco1Callback,
+ &IchnContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR( Status );
+ }
+
+ //
+ // Lock TCO_EN bit.
+ //
+ IoWrite16( mAcpiBaseAddr + R_PCH_TCO_CNT, IoRead16( mAcpiBaseAddr + R_PCH_TCO_CNT ) | B_PCH_TCO_CNT_LOCK );
+
+ //
+ // Set to power on from G3 dependent on WOL instead of AC Loss variable in order to support WOL from G3 feature.
+ //
+ //
+ // Set wake from G3 dependent on AC Loss variable and Wake On LAN variable.
+ // This is because no matter how, if WOL enabled or AC Loss variable not disabled, the board needs to wake from G3 to program the LAN WOL settings.
+ // This needs to be done after LAN enable/disable so that the PWR_FLR state clear not impacted the WOL from G3 feature.
+ //
+ if (mAcLossVariable != 0x00) {
+ SetAfterG3On (TRUE);
+ } else {
+ SetAfterG3On (FALSE);
+ }
+
+
+
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+SmmReadyToBootCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+ EFI_STATUS Status;
+
+ if (mSetSmmVariableProtocolSmiAllowed)
+ {
+ //
+ // It is okay to use gBS->LocateProtocol here because
+ // we are still in trusted execution.
+ //
+ Status = gBS->LocateProtocol(
+ &gEfiSmmVariableProtocolGuid,
+ NULL,
+ (void **)&mSmmVariable
+ );
+
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // mSetSmmVariableProtocolSmiAllowed will prevent this function from
+ // being executed more than 1 time.
+ //
+ mSetSmmVariableProtocolSmiAllowed = FALSE;
+ }
+
+}
+
+/**
+
+ @param DispatchHandle The handle of this callback, obtained when registering
+ @param DispatchContext The predefined context which contained sleep type and phase
+
+
+ @retval EFI_SUCCESS Operation successfully performed
+
+**/
+EFI_STATUS
+EFIAPI
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SaveRuntimeScriptTable ();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Workaround for S3 wake hang if C State is enabled
+ //
+ CpuSmmSxWorkAround();
+
+ return EFI_SUCCESS;
+}
+
+VOID
+CpuSmmSxWorkAround(
+ )
+{
+ UINT64 MsrValue;
+
+ MsrValue = AsmReadMsr64 (0xE2);
+
+ if (MsrValue & BIT15) {
+ return;
+ }
+
+ if (MsrValue & BIT10) {
+ MsrValue &= ~BIT10;
+ AsmWriteMsr64 (0xE2, MsrValue);
+ }
+}
+
+VOID
+ClearP2PBusMaster(
+ )
+{
+ UINT8 Command;
+ UINT8 Index;
+
+ for (Index = 0; Index < sizeof(mPciBm)/sizeof(EFI_PCI_BUS_MASTER); Index++) {
+ Command = MmioRead8 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ mPciBm[Index].Device,
+ mPciBm[Index].Function,
+ PCI_COMMAND_OFFSET
+ )
+ );
+ Command &= ~EFI_PCI_COMMAND_BUS_MASTER;
+ MmioWrite8 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ mPciBm[Index].Device,
+ mPciBm[Index].Function,
+ PCI_COMMAND_OFFSET
+ ),
+ Command
+ );
+ }
+}
+
+/**
+
+ Set the AC Loss to turn on or off.
+
+**/
+VOID
+SetAfterG3On (
+ BOOLEAN Enable
+ )
+{
+ UINT8 PmCon1;
+
+ //
+ // ICH handling portion
+ //
+ PmCon1 = MmioRead8 ( PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1 );
+ PmCon1 &= ~B_PCH_PMC_GEN_PMCON_AFTERG3_EN;
+ if (Enable) {
+ PmCon1 |= B_PCH_PMC_GEN_PMCON_AFTERG3_EN;
+ }
+ MmioWrite8 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, PmCon1);
+
+}
+
+/**
+ When a power button event happens, it shuts off the machine
+
+**/
+VOID
+EFIAPI
+PowerButtonCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+ //
+ // Check what the state to return to after AC Loss. If Last State, then
+ // set it to Off.
+ //
+ UINT16 data16;
+
+ if (mWakeOnRtcVariable) {
+ EnableS5WakeOnRtc();
+ }
+
+ if (mAcLossVariable == 1) {
+ SetAfterG3On (TRUE);
+ }
+
+ ClearP2PBusMaster();
+
+ //
+ // Program clock chip
+ //
+ S4S5ProgClock();
+
+
+ data16 = (UINT16)(IoRead16(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN));
+ data16 &= B_PCH_ACPI_GPE0a_EN_PCI_EXP;
+
+
+ //
+ // Clear Sleep SMI Status
+ //
+ IoWrite16 (mAcpiBaseAddr + R_PCH_SMI_STS,
+ (UINT16)(IoRead16 (mAcpiBaseAddr + R_PCH_SMI_STS) | B_PCH_SMI_STS_ON_SLP_EN));
+ //
+ // Clear Sleep Type Enable
+ //
+ IoWrite16 (mAcpiBaseAddr + R_PCH_SMI_EN,
+ (UINT16)(IoRead16 (mAcpiBaseAddr + R_PCH_SMI_EN) & (~B_PCH_SMI_EN_ON_SLP_EN)));
+
+ //
+ // Clear Power Button Status
+ //
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ //
+ // Shut it off now!
+ //
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, V_PCH_ACPI_PM1_CNT_S5);
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, B_PCH_ACPI_PM1_CNT_SLP_EN | V_PCH_ACPI_PM1_CNT_S5);
+
+ //
+ // Should not return
+ //
+ CpuDeadLoop();
+}
+
+
+/**
+ @param DispatchHandle - The handle of this callback, obtained when registering
+
+ @param DispatchContext - The predefined context which contained sleep type and phase
+
+**/
+VOID
+EFIAPI
+S5SleepAcLossCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+ //
+ // Check what the state to return to after AC Loss. If Last State, then
+ // set it to Off.
+ //
+ if (mAcLossVariable == 1) {
+ SetAfterG3On (TRUE);
+ }
+}
+
+/**
+
+ @param DispatchHandle The handle of this callback, obtained when registering
+ @param DispatchContext The predefined context which contained sleep type and phase
+
+ @retval Clears the Save State bit in the clock.
+
+**/
+VOID
+EFIAPI
+S4S5CallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+
+ UINT32 Data32;
+
+ //
+ // Enable/Disable USB Charging
+ //
+ if (mSystemConfiguration.UsbCharging == 0x01) {
+ Data32 = IoRead32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL);
+ Data32 |= BIT8;
+ IoWrite32(GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL, Data32);
+ }
+
+}
+
+
+VOID
+S4S5ProgClock()
+{
+}
+
+/**
+ SMI handler to enable ACPI mode
+
+ Dispatched on reads from APM port with value 0xA0
+
+ Disables the SW SMI Timer.
+ ACPI events are disabled and ACPI event status is cleared.
+ SCI mode is then enabled.
+
+ Disable SW SMI Timer
+
+ Clear all ACPI event status and disable all ACPI events
+ Disable PM sources except power button
+ Clear status bits
+
+ Disable GPE0 sources
+ Clear status bits
+
+ Disable GPE1 sources
+ Clear status bits
+
+ Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm")
+
+ Enable SCI
+
+ @param DispatchHandle - EFI Handle
+ @param DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+ @retval Nothing
+
+**/
+VOID
+EFIAPI
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+ UINT32 SmiEn;
+ UINT16 Pm1Cnt;
+ UINT16 wordValue;
+ UINT32 RegData32;
+
+ //
+ // Disable SW SMI Timer
+ //
+ SmiEn = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN);
+ SmiEn &= ~B_PCH_SMI_STS_SWSMI_TMR;
+ IoWrite32(mAcpiBaseAddr + R_PCH_SMI_EN, SmiEn);
+
+ wordValue = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS);
+ if(wordValue & B_PCH_ACPI_PM1_STS_WAK) {
+ IoWrite32((mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN), 0x0000);
+ IoWrite32((mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS), 0xffffffff);
+ }
+ else {
+ mPM1_SaveState16 = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN);
+
+ //
+ // Disable PM sources except power button
+ //
+ // power button is enabled only for PCAT. Disabled it on Tablet platform
+ //
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, B_PCH_ACPI_PM1_EN_PWRBTN);
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, 0xffff);
+
+ mGPE_SaveState32 = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN);
+ IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN, 0x0000);
+ IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS, 0xffffffff);
+
+ }
+
+ //
+ // Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm")
+ // Clear Status D reg VM bit, Date of month Alarm to make Data in CMOS RAM is no longer Valid
+ //
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D);
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x0);
+
+
+ RegData32 = IoRead32(ACPI_BASE_ADDRESS + R_PCH_ALT_GP_SMI_EN);
+ RegData32 &= ~(BIT7);
+ IoWrite32((ACPI_BASE_ADDRESS + R_PCH_ALT_GP_SMI_EN), RegData32);
+
+
+ //
+ // Enable SCI
+ //
+ Pm1Cnt = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT);
+ Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SCI_EN;
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
+
+
+}
+
+/**
+ SMI handler to disable ACPI mode
+
+ Dispatched on reads from APM port with value 0xA1
+
+ ACPI events are disabled and ACPI event status is cleared.
+ SCI mode is then disabled.
+ Clear all ACPI event status and disable all ACPI events
+ Disable PM sources except power button
+ Clear status bits
+ Disable GPE0 sources
+ Clear status bits
+ Disable GPE1 sources
+ Clear status bits
+ Disable SCI
+
+ @param DispatchHandle - EFI Handle
+ @param DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+ @retval Nothing
+
+**/
+VOID
+EFIAPI
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+ UINT16 Pm1Cnt;
+
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, 0xffff);
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, mPM1_SaveState16);
+
+ IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS, 0xffffffff);
+ IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN, mGPE_SaveState32);
+
+ //
+ // Disable SCI
+ //
+ Pm1Cnt = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT);
+ Pm1Cnt &= ~B_PCH_ACPI_PM1_CNT_SCI_EN;
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
+
+}
+
+/**
+ When an unknown event happen.
+
+ @retval None
+
+**/
+VOID
+DummyTco1Callback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+}
+
+UINTN
+DevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Start;
+
+ if (DevicePath == NULL) {
+ return 0;
+ }
+
+ //
+ // Search for the end of the device path structure
+ //
+ Start = DevicePath;
+ while (!IsDevicePathEnd (DevicePath)) {
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ //
+ // Compute the size and add back in the size of the end device path structure
+ //
+ return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL);
+}
+
+/**
+
+ @param DispatchHandle The handle of this callback, obtained when registering
+ @param DispatchContext The predefined context which contained sleep type and phase
+
+**/
+VOID
+S5SleepWakeOnRtcCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ )
+{
+ EnableS5WakeOnRtc();
+}
+
+/**
+
+ @retval 1. Check Alarm interrupt is not set.
+ 2. Clear Alarm interrupt.
+ 2. Set RTC wake up date and time.
+ 2. Enable RTC wake up alarm.
+ 3. Enable ICH PM1 EN Bit 10(RTC_EN)
+
+**/
+VOID
+EnableS5WakeOnRtc()
+{
+ UINT8 CmosData;
+ UINTN i;
+ EFI_STATUS Status;
+ UINTN VarSize;
+
+ //
+ // make sure EFI_SMM_VARIABLE_PROTOCOL is available
+ //
+ if (!mSmmVariable) {
+ return;
+ }
+
+ VarSize = sizeof(SYSTEM_CONFIGURATION);
+
+ //
+ // read the variable into the buffer
+ //
+ Status = mSmmVariable->SmmGetVariable(
+ L"Setup",
+ &gEfiSetupVariableGuid,
+ NULL,
+ &VarSize,
+ &mSystemConfiguration
+ );
+ if (EFI_ERROR(Status) || (!mSystemConfiguration.WakeOnRtcS5)) {
+ return;
+ }
+ mWakeupDay = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupDate);
+ mWakeupHour = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupTimeHour);
+ mWakeupMinute = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupTimeMinute);
+ mWakeupSecond = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupTimeSecond);
+
+ //
+ // Check RTC alarm interrupt is enabled. If enabled, someone already
+ // grabbed RTC alarm. Just return.
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
+ if(IoRead8(PCAT_RTC_DATA_REGISTER) & B_RTC_ALARM_INT_ENABLE){
+ return;
+ }
+
+ //
+ // Set Date
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D);
+ CmosData = IoRead8(PCAT_RTC_DATA_REGISTER);
+ CmosData &= ~(B_RTC_DATE_ALARM_MASK);
+ CmosData |= mWakeupDay ;
+ for(i = 0 ; i < 0xffff ; i++){
+ IoWrite8(PCAT_RTC_DATA_REGISTER, CmosData);
+ SmmStall(1);
+ if(((CmosData = IoRead8(PCAT_RTC_DATA_REGISTER)) & B_RTC_DATE_ALARM_MASK)
+ == mWakeupDay){
+ break;
+ }
+ }
+
+ //
+ // Set Second
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECOND_ALARM);
+ for(i = 0 ; i < 0xffff ; i++){
+ IoWrite8(PCAT_RTC_DATA_REGISTER, mWakeupSecond);
+ SmmStall(1);
+ if(IoRead8(PCAT_RTC_DATA_REGISTER) == mWakeupSecond){
+ break;
+ }
+ }
+
+ //
+ // Set Minute
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTE_ALARM);
+ for(i = 0 ; i < 0xffff ; i++){
+ IoWrite8(PCAT_RTC_DATA_REGISTER, mWakeupMinute);
+ SmmStall(1);
+ if(IoRead8(PCAT_RTC_DATA_REGISTER) == mWakeupMinute){
+ break;
+ }
+ }
+
+ //
+ // Set Hour
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOUR_ALARM);
+ for(i = 0 ; i < 0xffff ; i++){
+ IoWrite8(PCAT_RTC_DATA_REGISTER, mWakeupHour);
+ SmmStall(1);
+ if(IoRead8(PCAT_RTC_DATA_REGISTER) == mWakeupHour){
+ break;
+ }
+ }
+
+ //
+ // Wait for UIP to arm RTC alarm
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
+ while (IoRead8(PCAT_RTC_DATA_REGISTER) & 0x80);
+
+ //
+ // Read RTC register 0C to clear pending RTC interrupts
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C);
+ IoRead8(PCAT_RTC_DATA_REGISTER);
+
+ //
+ // Enable RTC Alarm Interrupt
+ //
+ IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
+ IoWrite8(PCAT_RTC_DATA_REGISTER, IoRead8(PCAT_RTC_DATA_REGISTER) | B_RTC_ALARM_INT_ENABLE);
+
+ //
+ // Clear ICH RTC Status
+ //
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_RTC);
+
+ //
+ // Enable ICH RTC event
+ //
+ IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN,
+ (UINT16)(IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN) | B_PCH_ACPI_PM1_EN_RTC));
+}
+
+UINT8
+HexToBcd(
+ IN UINT8 HexValue
+ )
+{
+ UINTN HighByte;
+ UINTN LowByte;
+
+ HighByte = (UINTN)HexValue / 10;
+ LowByte = (UINTN)HexValue % 10;
+
+ return ((UINT8)(LowByte + (HighByte << 4)));
+}
+
+UINT8
+BcdToHex(
+ IN UINT8 BcdValue
+ )
+{
+ UINTN HighByte;
+ UINTN LowByte;
+
+ HighByte = (UINTN)((BcdValue >> 4) * 10);
+ LowByte = (UINTN)(BcdValue & 0x0F);
+
+ return ((UINT8)(LowByte + HighByte));
+}
+
diff --git a/Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf b/Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf
new file mode 100644
index 000000000..69e0a5d99
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf
@@ -0,0 +1,98 @@
+#
+#
+# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#
+# Module Name:
+#
+# Platform.inf
+#
+# Abstract:
+#
+# Component description file for SMM Platform handler module
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformSmm
+ FILE_GUID = 99C20A37-042A-46e2-80F4-E4027FDBC86F
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializePlatformSmm
+ PI_SPECIFICATION_VERSION = 0x0001000A
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ S3Save.c
+ Platform.c
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ DebugLib
+ IoLib
+ BaseLib
+ BaseMemoryLib
+ DevicePathLib
+ HobLib
+ S3BootScriptLib
+ StallSmmLib
+ PchPlatformLib
+
+[Guids]
+ gEfiSetupVariableGuid
+ gDmiDataGuid
+ gEfiAcpiVariableCompatiblityGuid
+ gEfiPciLanInfoGuid
+ gEfiPciLanInfoGuid
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+
+[Protocols]
+ gEfiSmmBaseProtocolGuid
+ gEfiSmmIchnDispatchProtocolGuid
+ gEfiGlobalNvsAreaProtocolGuid
+ gEfiSmmSwDispatchProtocolGuid
+ gEfiSmmPowerButtonDispatchProtocolGuid
+ gEfiSmmSxDispatchProtocolGuid
+ gEfiSmmVariableProtocolGuid
+ gEfiCpuIo2ProtocolGuid
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec
+ Vlv2TbltDevicePkg/PlatformPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[Pcd.common]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Depex]
+ gEfiSmmBaseProtocolGuid AND
+ gEfiSmmAccess2ProtocolGuid AND
+ gEfiSmmPowerButtonDispatchProtocolGuid AND
+ gEfiSmmSxDispatchProtocolGuid AND
+ gEfiSmmIchnDispatchProtocolGuid AND
+ gEfiSmmSwDispatchProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiGlobalNvsAreaProtocolGuid
+
diff --git a/Vlv2TbltDevicePkg/PlatformSmm/S3Save.c b/Vlv2TbltDevicePkg/PlatformSmm/S3Save.c
new file mode 100644
index 000000000..8c7112bf0
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformSmm/S3Save.c
@@ -0,0 +1,382 @@
+/** @file
+
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+
+Module Name:
+
+ IchS3Save.c
+
+Abstract:
+
+ SMM S3 handler Driver implementation file
+
+Revision History
+
+**/
+#include "SmmPlatform.h"
+
+extern UINT16 mAcpiBaseAddr;
+EFI_PHYSICAL_ADDRESS mRuntimeScriptTableBase;
+
+EFI_STATUS
+InitRuntimeScriptTable (
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 VarAttrib;
+ UINTN VarSize;
+ ACPI_VARIABLE_SET_COMPATIBILITY *AcpiVariableBase;
+
+ //
+ // Allocate runtime ACPI script table space. We need it to save some
+ // settings done by CSM, which runs after normal script table closed
+ //
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiACPIReclaimMemory,
+ 1,
+ &mRuntimeScriptTableBase
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_OUT_OF_RESOURCES ;
+ }
+
+ //
+ // Save runtime script table base into global ACPI variable
+ //
+ VarAttrib = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
+ | EFI_VARIABLE_NON_VOLATILE;
+ VarSize = sizeof (UINTN);
+ Status = SystemTable->RuntimeServices->GetVariable (
+ ACPI_GLOBAL_VARIABLE,
+ &gEfiAcpiVariableCompatiblityGuid,
+ &VarAttrib,
+ &VarSize,
+ &AcpiVariableBase
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ AcpiVariableBase->RuntimeScriptTableBase = mRuntimeScriptTableBase;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+ VOID
+ )
+{
+ SMM_PCI_IO_ADDRESS PciAddress;
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT8 Data8;
+ UINT8 Mask;
+ UINTN Index;
+ UINTN Offset;
+ UINT8 RegTable[] = {
+
+ //
+ //Bus , Dev, Func, DMI
+ //
+ 0x00 , 0x00, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x00 , 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0xa0,
+
+ //
+ //Bus , Dev, Func, LPC device
+ //
+ 0x00 , 0x1F, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x00 , 0x08, 0x00, 0x07, 0x00, 0x00, 0x90, 0x00,
+
+ //
+ //Bus , Dev, Func, PCIE device
+ //
+ 0x00 , 0x1C, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0xC0 , 0x83, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, PCIE device
+ //
+ 0x00 , 0x1C, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x03 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, SATA device
+ //
+ 0x00 , 0x13, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0xf4 , 0xab, 0x27, 0x10, 0xf1, 0x1d, 0x00, 0x40,
+
+ //
+ //Bus , Dev, Func, EHCI device
+ //
+ 0x00 , 0x1D, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x10 , 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+
+ //
+ //Bus , Dev, Func, SMBUS device
+ //
+ 0x00 , 0x1f, 0x03,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x10 , 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, SMBUS device
+ //
+ 0x00 , 0x1f, 0x03,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, VGA bus1
+ //
+ 0x01 , 0x00, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x58 , 0x81, 0x18, 0x01, 0xb0, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, VGA bus1
+ //
+ 0x01 , 0x00, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, VGA bus1 function 1
+ //
+ 0x01 , 0x00, 0x01,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x51 , 0x80, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, VGA bus1 function 1
+ //
+ 0x01 , 0x00, 0x01,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, IGD bus0 function 0
+ //
+ 0x00 , 0x02, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x42 , 0x81, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+
+ //
+ //Bus , Dev, Func, USB bus0 function 0
+ //
+ 0x00 , 0x16, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, HD Audio bus0 function 0
+ //
+ 0x00 , 0x1B, 0x00,
+
+ //
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ //
+ 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+
+ //
+ //0xFF indicates the end of the table
+ //
+ 0xFF
+ };
+
+ //
+ // These registers have to set in byte order
+ //
+ UINT8 ExtReg[] = { 0x9E, 0x9D }; // SMRAM settings
+
+
+
+ //
+ // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
+ // and vital to S3 resume. That's why we put save code here
+ //
+ PciAddress.Bus = 0;
+ PciAddress.Device = 0;
+ PciAddress.Function = 0;
+ PciAddress.ExtendedRegister = 0;
+
+ for (Index = 0; Index < 2; Index++) {
+ //
+ // Read SRAM setting from Pci(0, 0, 0)
+ //
+ PciAddress.Register = ExtReg[Index];
+ Data8 = MmioRead8 (
+ MmPciAddress (0,
+ PciAddress.Bus,
+ PciAddress.Device,
+ PciAddress.Function,
+ PciAddress.Register
+ )
+ );
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite(
+ S3BootScriptWidthUint8,
+ *(UINT64*)&PciAddress,
+ 1,
+ &Data8
+ );
+ }
+
+
+ //
+ // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
+ // and vital to S3 resume. That's why we put save code here
+ //
+ Index = 0;
+ while (RegTable[Index] != 0xFF) {
+
+ PciAddress.Bus = RegTable[Index++];
+ PciAddress.Device = RegTable[Index++];
+ PciAddress.Function = RegTable[Index++];
+ PciAddress.Register = 0;
+ PciAddress.ExtendedRegister = 0;
+
+ Data16 = MmioRead16 (
+ MmPciAddress (0,
+ PciAddress.Bus,
+ PciAddress.Device,
+ PciAddress.Function,
+ PciAddress.Register
+ )
+ );
+
+ if (Data16 == 0xFFFF) {
+ Index+=8;
+ continue;
+ }
+
+ for (Offset = 0, Mask = 0x01; Offset < 256; Offset+=4, Mask<<=1) {
+
+ if (Mask == 0x00) {
+ Mask = 0x01;
+ }
+
+ if (RegTable[Index + Offset/32] & Mask ) {
+
+ PciAddress.Register = (UINT8)Offset;
+ Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ *(UINT64*)&PciAddress,
+ 1,
+ &Data32
+ );
+ }
+ }
+
+ Index += 8;
+
+ }
+
+
+ //
+ // Save I/O ports to S3 script table
+ //
+
+ //
+ // Selftest KBC
+ //
+ Data8 = 0xAA;
+ S3BootScriptSaveIoWrite (
+ S3BootScriptWidthUint8,
+ 0x64,
+ (UINTN)1,
+ &Data8
+ );
+
+ Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN);
+
+ S3BootScriptSaveIoWrite (
+ S3BootScriptWidthUint32,
+ (mAcpiBaseAddr + R_PCH_SMI_EN),
+ 1,
+ &Data32
+ );
+
+ //
+ // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path.
+ //
+ Data16 = IoRead16(mAcpiBaseAddr + R_PCH_TCO_CNT);
+
+ S3BootScriptSaveIoWrite (
+ S3BootScriptWidthUint16,
+ mAcpiBaseAddr + R_PCH_TCO_CNT,
+ 1,
+ &Data16
+ );
+
+
+ return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h b/Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h
new file mode 100644
index 000000000..0bf76dd37
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h
@@ -0,0 +1,245 @@
+/*++
+
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ SmmPlatform.h
+
+Abstract:
+
+ Header file for
+
+++*/
+
+#ifndef _PLATFORM_H
+#define _PLATFORM_H
+
+#include <PiSmm.h>
+
+
+
+#include <Protocol/SmmBase.h>
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/SmmPowerButtonDispatch.h>
+#include <Protocol/SmmSxDispatch.h>
+#include <Protocol/SmmSwDispatch.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmIchnDispatch.h>
+#include <Protocol/SmmAccess.h>
+#include <Protocol/SmmVariable.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadedImage.h>
+#include "Protocol/GlobalNvsArea.h"
+#include <Guid/AcpiVariableCompatibility.h>
+#include <Guid/SetupVariable.h>
+#include <Guid/EfiVpdData.h>
+#include <Guid/PciLanInfo.h>
+#include <IndustryStandard/Pci22.h>
+
+#include "PchAccess.h"
+#include "PlatformBaseAddresses.h"
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PchPlatformLib.h>
+#include <Library/StallSmmLib.h>
+
+
+
+typedef struct {
+ UINT8 Register;
+ UINT8 Function;
+ UINT8 Device;
+ UINT8 Bus;
+ UINT32 ExtendedRegister;
+} SMM_PCI_IO_ADDRESS;
+
+typedef struct {
+ CHAR8 BoardAaNumber[7];
+ UINTN BoardFabNumber;
+} BOARD_AA_NUMBER_DECODE;
+
+//
+// BugBug -- Need to get these two values from acpi.h, but right now, they are
+// declared in platform-specific variants of this file, so no easy
+// way to pick-up the include file and work across platforms.
+// Need these definitions to go into a file like common\acpi.h.
+//
+#define ACPI_ENABLE 0xA0
+#define ACPI_DISABLE 0xA1
+
+#define APM_12_FUNCS 0x50
+#define SMI_SET_SMMVARIABLE_PROTOCOL 0x51 // this is used in Cpu\Pentium\Smm\Base\SmmBase.c
+
+#define SMI_CMD_GET_MSEG_STATUS 0x70
+#define SMI_CMD_UPDATE_MSEG_SIZE 0x71
+#define SMI_CMD_LOAD_STM 0x72
+#define SMI_CMD_UNLOAD_STM 0x73
+#define SMI_CMD_GET_SMRAM_RANGES 0x74
+
+
+#define PCAT_RTC_ADDRESS_REGISTER 0x74
+#define PCAT_RTC_DATA_REGISTER 0x75
+
+#define RTC_ADDRESS_SECOND 0x00
+#define RTC_ADDRESS_SECOND_ALARM 0x01
+#define RTC_ADDRESS_MINUTE 0x02
+#define RTC_ADDRESS_MINUTE_ALARM 0x03
+#define RTC_ADDRESS_HOUR 0x04
+#define RTC_ADDRESS_HOUR_ALARM 0x05
+
+#define RTC_ADDRESS_REGISTER_A 0x0A
+#define RTC_ADDRESS_REGISTER_B 0x0B
+#define RTC_ADDRESS_REGISTER_C 0x0C
+#define RTC_ADDRESS_REGISTER_D 0x0D
+
+#define B_RTC_ALARM_INT_ENABLE 0x20
+#define B_RTC_ALARM_INT_STATUS 0x20
+
+#define B_RTC_DATE_ALARM_MASK 0x3F
+
+#define PCAT_CMOS_2_ADDRESS_REGISTER 0x72
+#define PCAT_CMOS_2_DATA_REGISTER 0x73
+
+#define EC_C_PORT 0x66
+#define SMC_SMI_DISABLE 0xBC
+#define SMC_ENABLE_ACPI_MODE 0xAA // Enable ACPI mode
+
+#define IO_MISC 156
+
+
+#define MAXIMUM_NUMBER_OF_PSTATES 12
+#define ICH_SMM_DATA_PORT 0xB3
+
+#define EFI_IA32_PMG_CST_CONFIG 0x000000E2
+#define B_EFI_CST_CONTROL_LOCK BIT15
+#define B_EFI_IO_MWAIT_REDIRECTION_ENABLE BIT10
+#define EFI_IA32_PMG_IO_CAPTURE_ADDR 0x000000E4
+
+extern EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo;
+
+//
+// Callback function prototypes
+//
+VOID
+EFIAPI
+PowerButtonCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+S5SleepWakeOnLanCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+EFIAPI
+S5SleepAcLossCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ );
+
+
+VOID
+EFIAPI
+S4S5CallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+EFIAPI
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+EFIAPI
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+EFIAPI
+SmmReadyToBootCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+DummyTco1Callback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext
+ );
+
+
+VOID
+PerrSerrCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+RiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext
+ );
+
+
+VOID
+SetAfterG3On (
+ BOOLEAN Enable
+ );
+
+VOID
+TurnOffVregUsb (
+ );
+
+VOID
+PStateSupportCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ );
+
+VOID
+PStateTransitionCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+ );
+
+EFI_STATUS
+EFIAPI
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext
+ );
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+ VOID
+ );
+
+
+#endif
+
diff --git a/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c
new file mode 100644
index 000000000..09a6a8c3b
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c
@@ -0,0 +1,257 @@
+/** @file
+
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+
+Module Name:
+
+
+ SmmScriptSave.c
+
+Abstract:
+
+ ScriptTableSave module at run time
+
+--*/
+
+#include "SmmScriptSave.h"
+
+//
+// internal functions
+//
+
+EFI_STATUS
+BootScriptIoWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ );
+
+EFI_STATUS
+BootScriptPciCfgWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ );
+
+VOID
+SmmCopyMem (
+ IN UINT8 *Destination,
+ IN UINT8 *Source,
+ IN UINTN ByteCount
+ );
+
+//
+// Function implementations
+//
+EFI_STATUS
+SmmBootScriptWrite (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type,
+ IN UINT16 OpCode,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+
+ if (ScriptTable == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Build script according to opcode
+ //
+ switch ( OpCode ) {
+
+ case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
+ VA_START(Marker, OpCode);
+ Status = BootScriptIoWrite (ScriptTable, Marker);
+ VA_END(Marker);
+ break;
+
+ case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
+ VA_START(Marker, OpCode);
+ Status = BootScriptPciCfgWrite(ScriptTable, Marker);
+ VA_END(Marker);
+ break;
+
+ default:
+ Status = EFI_SUCCESS;
+ break;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+SmmBootScriptCreateTable (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type
+ )
+{
+ BOOT_SCRIPT_POINTERS Script;
+ UINT8 *Buffer;
+
+ if (ScriptTable == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = (UINT8*) ((UINTN)(*ScriptTable));
+
+ //
+ // Fill Table Header
+ //
+ Script.Raw = Buffer;
+ Script.TableInfo->OpCode = EFI_BOOT_SCRIPT_TABLE_OPCODE;
+ Script.TableInfo->Length = sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);
+ Script.TableInfo->TableLength = sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);
+
+ //
+ // Update current table pointer
+ //
+ *ScriptTable = *ScriptTable + sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+SmmBootScriptCloseTable (
+ IN EFI_SMM_SCRIPT_TABLE ScriptTableBase,
+ IN EFI_SMM_SCRIPT_TABLE ScriptTablePtr,
+ IN UINTN Type
+ )
+{
+ BOOT_SCRIPT_POINTERS Script;
+
+ //
+ // Add final "termination" node to script table
+ //
+ Script.Raw = (UINT8*) ((UINTN)ScriptTablePtr);
+ Script.Terminate->OpCode = EFI_BOOT_SCRIPT_TERMINATE_OPCODE;
+ Script.Terminate->Length = sizeof (EFI_BOOT_SCRIPT_TERMINATE);
+ ScriptTablePtr += sizeof (EFI_BOOT_SCRIPT_TERMINATE);
+
+
+ //
+ // Update Table Header
+ //
+ Script.Raw = (UINT8*) ((UINTN)ScriptTableBase);
+ Script.TableInfo->OpCode = EFI_BOOT_SCRIPT_TABLE_OPCODE;
+ Script.TableInfo->Length = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
+ Script.TableInfo->TableLength = (UINT32)(ScriptTablePtr - ScriptTableBase);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+BootScriptIoWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ )
+{
+ BOOT_SCRIPT_POINTERS Script;
+ EFI_BOOT_SCRIPT_WIDTH Width;
+ UINTN Address;
+ UINTN Count;
+ UINT8 *Buffer;
+ UINTN NodeLength;
+ UINT8 WidthInByte;
+
+ Width = VA_ARG(Marker, EFI_BOOT_SCRIPT_WIDTH);
+ Address = VA_ARG(Marker, UINTN);
+ Count = VA_ARG(Marker, UINTN);
+ Buffer = VA_ARG(Marker, UINT8*);
+
+ WidthInByte = (UINT8)(0x01 << (Width & 0x03));
+ Script.Raw = (UINT8*) ((UINTN)(*ScriptTable));
+ NodeLength = sizeof (EFI_BOOT_SCRIPT_IO_WRITE) + (WidthInByte * Count);
+
+ //
+ // Build script data
+ //
+ Script.IoWrite->OpCode = EFI_BOOT_SCRIPT_IO_WRITE_OPCODE;
+ Script.IoWrite->Length = (UINT8)(NodeLength);
+ Script.IoWrite->Width = Width;
+ Script.IoWrite->Address = Address;
+ Script.IoWrite->Count = (UINT32)Count;
+ SmmCopyMem (
+ (UINT8*)(Script.Raw + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)),
+ Buffer,
+ WidthInByte * Count
+ );
+
+ //
+ // Update Script table pointer
+ //
+ *ScriptTable = *ScriptTable + NodeLength;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+BootScriptPciCfgWrite (
+ IN EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN VA_LIST Marker
+ )
+{
+ BOOT_SCRIPT_POINTERS Script;
+ EFI_BOOT_SCRIPT_WIDTH Width;
+ UINT64 Address;
+ UINTN Count;
+ UINT8 *Buffer;
+ UINTN NodeLength;
+ UINT8 WidthInByte;
+
+ Width = VA_ARG(Marker, EFI_BOOT_SCRIPT_WIDTH);
+ Address = VA_ARG(Marker, UINT64);
+ Count = VA_ARG(Marker, UINTN);
+ Buffer = VA_ARG(Marker, UINT8*);
+
+ WidthInByte = (UINT8)(0x01 << (Width & 0x03));
+ Script.Raw = (UINT8*) ((UINTN)(*ScriptTable));
+ NodeLength = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count);
+
+ //
+ // Build script data
+ //
+ Script.PciWrite->OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE;
+ Script.PciWrite->Length = (UINT8)(NodeLength);
+ Script.PciWrite->Width = Width;
+ Script.PciWrite->Address = Address;
+ Script.PciWrite->Count = (UINT32)Count;
+ SmmCopyMem (
+ (UINT8*)(Script.Raw + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)),
+ Buffer,
+ WidthInByte * Count
+ );
+
+ //
+ // Update Script table pointer
+ //
+ *ScriptTable = *ScriptTable + NodeLength;
+ return EFI_SUCCESS;
+}
+
+VOID
+SmmCopyMem (
+ IN UINT8 *Destination,
+ IN UINT8 *Source,
+ IN UINTN ByteCount
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < ByteCount; Index++, Destination++, Source++) {
+ *Destination = *Source;
+ }
+}
diff --git a/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h
new file mode 100644
index 000000000..e2e4bb6b2
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h
@@ -0,0 +1,55 @@
+/*++
+
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+
+Module Name:
+
+ SmmScriptSave.h
+
+Abstract:
+
+ This is an implementation of the BootScript at run time.
+
+--*/
+
+#ifndef _RUNTIME_SCRIPT_SAVE_H
+#define _RUNTIME_SCRIPT_SAVE_H
+
+#include "Efi.h"
+#include "EfiBootScript.h"
+
+
+typedef EFI_PHYSICAL_ADDRESS EFI_SMM_SCRIPT_TABLE;
+
+EFI_STATUS
+SmmBootScriptCreateTable (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type
+ );
+
+EFI_STATUS
+SmmBootScriptWrite (
+ IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable,
+ IN UINTN Type,
+ IN UINT16 OpCode,
+ ...
+ );
+
+EFI_STATUS
+SmmBootScriptCloseTable (
+ IN EFI_SMM_SCRIPT_TABLE ScriptTableBase,
+ IN EFI_SMM_SCRIPT_TABLE ScriptTablePtr,
+ IN UINTN Type
+ );
+
+#endif