From 3cbfba02fef9dae07a041fdbf2e89611d72d6f90 Mon Sep 17 00:00:00 2001 From: David Wei Date: Mon, 12 Jan 2015 09:37:20 +0000 Subject: 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 Reviewed-by: Mike Wu Reviewed-by: Hot Tian git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16599 6f19259b-4bc3-4df7-8a09-765794883524 --- Vlv2TbltDevicePkg/PlatformSmm/Platform.c | 977 ++++++++++++++++++++++++++ Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf | 98 +++ Vlv2TbltDevicePkg/PlatformSmm/S3Save.c | 382 ++++++++++ Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h | 245 +++++++ Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c | 257 +++++++ Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h | 55 ++ 6 files changed, 2014 insertions(+) create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/Platform.c create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/S3Save.c create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h (limited to 'Vlv2TbltDevicePkg/PlatformSmm') diff --git a/Vlv2TbltDevicePkg/PlatformSmm/Platform.c b/Vlv2TbltDevicePkg/PlatformSmm/Platform.c new file mode 100644 index 0000000000..d8bfeb4371 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/Platform.c @@ -0,0 +1,977 @@ +/** @file + + Copyright (c) 2004 - 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.c + +Abstract: + + This is a generic template for a child of the IchSmm driver. + + +--*/ + +#include "SmmPlatform.h" +#include + + +// +// 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 0000000000..69e0a5d990 --- /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 0000000000..8c7112bf0b --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/S3Save.c @@ -0,0 +1,382 @@ +/** @file + + Copyright (c) 2004 - 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: + + 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 0000000000..0bf76dd37a --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h @@ -0,0 +1,245 @@ +/*++ + + Copyright (c) 2004 - 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: + + SmmPlatform.h + +Abstract: + + Header file for + +++*/ + +#ifndef _PLATFORM_H +#define _PLATFORM_H + +#include + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Protocol/GlobalNvsArea.h" +#include +#include +#include +#include +#include + +#include "PchAccess.h" +#include "PlatformBaseAddresses.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +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 0000000000..09a6a8c3b5 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c @@ -0,0 +1,257 @@ +/** @file + + Copyright (c) 2004 - 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: + + + 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 0000000000..e2e4bb6b27 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h @@ -0,0 +1,55 @@ +/*++ + + Copyright (c) 2004 - 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: + + 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 -- cgit v1.2.3