summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-06-01 14:45:10 +0800
committerHao Wu <hao.a.wu@intel.com>2016-06-07 09:56:05 +0800
commit2155fde63146669d38905df81694b1002ace4795 (patch)
treeca05e021fa7e9f37f60b3a66622e420c4253925e
parent69b6f5b6c5ee230044182f5a8036f6ed99ff90da (diff)
downloadedk2-platforms-2155fde63146669d38905df81694b1002ace4795.tar.xz
BraswellPlatformPkg: Add AcpiSmm
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
-rw-r--r--BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.h243
-rw-r--r--BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.inf103
-rw-r--r--BraswellPlatformPkg/Acpi/AcpiSmm/Platform.c831
-rw-r--r--BraswellPlatformPkg/Acpi/AcpiSmm/S3Save.c402
4 files changed, 1579 insertions, 0 deletions
diff --git a/BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.h b/BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.h
new file mode 100644
index 0000000000..256b8d844a
--- /dev/null
+++ b/BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.h
@@ -0,0 +1,243 @@
+/** @file
+ SMM handler driver implementation.
+
+ Copyright (c) 2004 - 2015, Intel Corporation. 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 _PLATFORM_H
+#define _PLATFORM_H
+
+#include <PiSmm.h>
+#include <Protocol/SmmBase.h>
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/SmmPowerButtonDispatch2.h>
+#include <Protocol/SmmSxDispatch2.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/AcpiVariable.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>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <ReservedAcpiS3Range.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
+//
+EFI_STATUS
+EFIAPI
+PowerButtonCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+S5SleepWakeOnLanCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+S5SleepAcLossCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+S4S5CallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+DummyTco1Callback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+VOID
+PerrSerrCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+VOID
+RiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+VOID
+SetAfterG3On (
+ BOOLEAN Enable
+ );
+
+VOID
+TurnOffVregUsb (
+ );
+
+EFI_STATUS
+PStateSupportCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+PStateTransitionCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+ VOID
+ );
+
+#endif
+
diff --git a/BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.inf b/BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.inf
new file mode 100644
index 0000000000..6f9950266d
--- /dev/null
+++ b/BraswellPlatformPkg/Acpi/AcpiSmm/AcpiSmm.inf
@@ -0,0 +1,103 @@
+## @file
+# Component description file for SMM Platform handler module
+#
+# Provides platform specific handlers for different SMI events. The module will
+# register handlers for sleep state transitions as well as other software SMI
+# events.
+#
+# Copyright (c) 1999 - 2015, Intel Corporation. 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 = PlatformSmm
+ FILE_GUID = 88802B98-ADFE-4414-A695-FB35CA8D11F2
+ 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
+ ReportStatusCodeLib
+
+[Guids]
+
+ ## SOMETIMES_CONSUMES ## Variable:L"AcpiGlobalVariable"
+ gEfiAcpiVariableCompatiblityGuid
+
+ ## SOMETIMES_CONSUMES
+ gEfiAcpiVariableGuid
+
+[Protocols]
+ ## CONSUMES
+ gEfiSmmIchnDispatchProtocolGuid
+
+ ## CONSUMES
+ gEfiGlobalNvsAreaProtocolGuid
+
+ ## CONSUMES
+ gEfiSmmSwDispatch2ProtocolGuid
+
+ ## SOMETIMES_CONSUMES
+ gEfiSmmPowerButtonDispatch2ProtocolGuid
+
+ ## CONSUMES
+ gEfiSmmSxDispatch2ProtocolGuid
+
+ ## CONSUMES
+ gEfiSmmVariableProtocolGuid
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ ChvRefCodePkg/ChvRefCodePkg.dec
+ BraswellPlatformPkg/BraswellPlatformPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[Pcd]
+ ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart ## CONSUMES
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## SOMETIMES_CONSUMES
+ gEfiEdkIIPlatformTokenSpaceGuid.PcdSystemConfiguration
+
+[Depex]
+ gEfiSmmBase2ProtocolGuid AND
+ gEfiSmmAccess2ProtocolGuid AND
+ gEfiSmmPowerButtonDispatch2ProtocolGuid AND
+ gEfiSmmSxDispatch2ProtocolGuid AND
+ gEfiSmmIchnDispatchProtocolGuid AND
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiVariableArchProtocolGuid
+
diff --git a/BraswellPlatformPkg/Acpi/AcpiSmm/Platform.c b/BraswellPlatformPkg/Acpi/AcpiSmm/Platform.c
new file mode 100644
index 0000000000..bf58f6ca41
--- /dev/null
+++ b/BraswellPlatformPkg/Acpi/AcpiSmm/Platform.c
@@ -0,0 +1,831 @@
+/** @file
+ Generic template for a child of the IchSmm driver.
+
+ Copyright (c) 2004 - 2015, Intel Corporation. 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.
+
+**/
+
+#include "AcpiSmm.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 },
+};
+
+UINT16 mAcpiBaseAddr;
+SYSTEM_CONFIGURATION mSystemConfiguration;
+UINT16 mPM1_SaveState16;
+UINT32 mGPE_SaveState32;
+
+//
+// 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
+EnableS5WakeOnRtc();
+
+UINT8
+HexToBcd (
+ UINT8 HexValue
+ );
+
+UINT8
+BcdToHex(
+ IN UINT8 BcdValue
+ );
+
+VOID
+CpuSmmSxWorkAround (
+ );
+
+
+/*++
+ Set the AC Loss to turn on or off.
+
+ @param[in] Turn on or off.
+
+ @retval None
+
+--*/
+
+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);
+
+}
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ VOID* Buffer;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Buffer = (VOID *) (UINTN) Address;
+ ZeroMem (Buffer, Size);
+
+ return Buffer;
+}
+
+EFI_STATUS
+EFIAPI
+AllocateS3AcpiReservedMemory (
+ VOID
+)
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINT64 MemoryLength;
+ RESERVED_ACPI_S3_RANGE *AcpiS3Range;
+ EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
+ VOID *GuidHob;
+ VOID *AcpiReservedBase;
+
+ //
+ // Calculate the system memory length by memory hobs
+ //
+ MemoryLength = 0x100000;
+
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ if (Hob.Raw == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ //
+ // Skip the memory region below 1MB
+ //
+ if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {
+ MemoryLength += Hob.ResourceDescriptor->ResourceLength;
+ }
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
+ }
+
+ //
+ // Find the location of reserved page in TSEG. This was reserved by the MRC.
+ //
+ GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+ if (GuidHob != NULL) {
+ SmramDescriptor = (EFI_SMRAM_DESCRIPTOR*) GET_GUID_HOB_DATA (GuidHob);
+
+ //
+ // Now find the location of the data structure that is used to store the address
+ // of the S3 reserved memory.
+ //
+ AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (SmramDescriptor->PhysicalStart +
+ RESERVED_ACPI_S3_RANGE_OFFSET);
+
+ //
+ // Allocate reserved ACPI memory for S3 resume. Pointer to this region is
+ // stored in SMRAM in the first page of TSEG.
+ //
+ AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (
+ PcdGet32 (PcdS3AcpiReservedMemorySize)
+ );
+ if (AcpiReservedBase != NULL) {
+ AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase;
+ AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);
+ }
+
+ AcpiS3Range->SystemMemoryLength = (UINT32)MemoryLength;
+
+ DEBUG ((EFI_D_ERROR, "S3 Memory Base: %08X\n", AcpiS3Range->AcpiReservedMemoryBase));
+ DEBUG ((EFI_D_ERROR, "S3 Memory Size: %08X\n", AcpiS3Range->AcpiReservedMemorySize));
+ DEBUG ((EFI_D_ERROR, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ Initializes the SMM Handler Driver
+
+ @param[in] ImageHandle
+ @param[in] SystemTable
+
+ @retval None
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatformSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT PowerButtonContext;
+ EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL *PowerButtonDispatch;
+ EFI_SMM_ICHN_DISPATCH_PROTOCOL *IchnDispatch;
+ EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;
+ EFI_SMM_SX_REGISTER_CONTEXT EntryDispatchContext;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
+ EFI_SMM_SW_REGISTER_CONTEXT SwContext;
+ EFI_BOOT_MODE BootMode;
+
+ Handle = NULL;
+
+ //
+ // Get the ACPI Base Address
+ //
+
+ mAcpiBaseAddr = PchLpcPciCfg16( R_PCH_LPC_ACPI_BASE ) & B_PCH_LPC_ACPI_BASE_BAR;
+
+ CopyMem (&mSystemConfiguration, PcdGetPtr (PcdSystemConfiguration), sizeof (SYSTEM_CONFIGURATION));
+ mAcLossVariable = mSystemConfiguration.StateAfterG3;
+ mWakeOnRtcVariable = mSystemConfiguration.WakeOnRtcS5;
+
+ BootMode = GetBootModeHob ();
+
+ //
+ // Get the Power Button protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmPowerButtonDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &PowerButtonDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {
+ //
+ // Register for the power button event
+ //
+ PowerButtonContext.Phase = EfiPowerButtonEntry;
+ Status = PowerButtonDispatch->Register (
+ PowerButtonDispatch,
+ PowerButtonCallback,
+ &PowerButtonContext,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Get the Sx dispatch protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &SxDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register entry phase call back function
+ //
+ EntryDispatchContext.Type = SxS3;
+ EntryDispatchContext.Phase = SxEntry;
+
+ Status = SxDispatch->Register (
+ SxDispatch,
+ 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 = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ 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);
+
+ //
+ // Get the ICHn protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmIchnDispatchProtocolGuid,
+ NULL,
+ (VOID **) &IchnDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SetAfterG3On (TRUE);
+
+ AllocateS3AcpiReservedMemory ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @param[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] DispatchContext The predefined context which contained sleep type and phase
+
+ @retval EFI_SUCCESS Operation successfully performed
+
+**/
+EFI_STATUS
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+
+{
+//
+// EFI_STATUS Status;
+//
+// REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart));
+// Status = SaveRuntimeScriptTable ();
+// if (EFI_ERROR (Status)) {
+// return Status;
+// }
+//
+ return EFI_SUCCESS;
+}
+
+/**
+ When a power button event happens, it shuts off the machine.
+
+ @param[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] DispatchContext The predefined context which contained sleep type and phase
+
+ @retval
+
+**/
+EFI_STATUS
+PowerButtonCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+
+ UINT16 data16;
+
+ //
+ // Set what the state to return to after AC Loss. If Last State, then
+ // set it to Off.
+ //
+ SetAfterG3On (TRUE);
+
+ if (mWakeOnRtcVariable) {
+ EnableS5WakeOnRtc();
+ }
+
+ 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
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ @param[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] DispatchContext The predefined context which contained sleep type and phase
+
+**/
+EFI_STATUS
+EFIAPI
+S5SleepAcLossCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ @param[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] DispatchContext The predefined context which contained sleep type and phase
+
+ @retval Clears the Save State bit in the clock.
+
+**/
+EFI_STATUS
+EFIAPI
+S4S5CallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ return EFI_SUCCESS;
+}
+
+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[in] DispatchHandle EFI Handle
+ @param[in] DispatchContext Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+ @retval Nothing
+
+**/
+EFI_STATUS
+EFIAPI
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ UINT16 Pm1Cnt;
+
+ //
+ // 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);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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[in] DispatchHandle EFI Handle
+ @param[in] DispatchContext Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+ @retval Nothing
+
+**/
+EFI_STATUS
+EFIAPI
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ 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);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ When an unknown event happen.
+
+ @param[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] DispatchContext The predefined context which contained sleep type and phase
+
+ @retval None
+
+**/
+EFI_STATUS
+EFIAPI
+DummyTco1Callback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ return EFI_SUCCESS;
+}
+
+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[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] DispatchContext The predefined context which contained sleep type and phase
+
+**/
+EFI_STATUS
+S5SleepWakeOnRtcCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ EnableS5WakeOnRtc();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @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;
+
+ if (!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/BraswellPlatformPkg/Acpi/AcpiSmm/S3Save.c b/BraswellPlatformPkg/Acpi/AcpiSmm/S3Save.c
new file mode 100644
index 0000000000..690cb12b88
--- /dev/null
+++ b/BraswellPlatformPkg/Acpi/AcpiSmm/S3Save.c
@@ -0,0 +1,402 @@
+/** @file
+ SMM S3 handler driver implementation.
+
+ Copyright (c) 2004 - 2015, Intel Corporation. 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.
+
+**/
+
+#include "AcpiSmm.h"
+
+extern UINT16 mAcpiBaseAddr;
+EFI_PHYSICAL_ADDRESS mRuntimeScriptTableBase;
+
+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,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+
+ //Bus , Dev, Func, CUnit Device
+ 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, IGD Device
+ 0x00 , 0x02, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x81, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00,
+
+ //Bus , Dev, Func, IUnit Device
+ 0x00 , 0x03, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, ISH Device
+ 0x00 , 0x0A, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, PUnit Device
+ 0x00 , 0x0B, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, eMMC Device
+ 0x00 , 0x10, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, SDIO Device
+ 0x00 , 0x11, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, SDCard Device
+ 0x00 , 0x12, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 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
+ 0xF2 , 0xA3, 0x27, 0x30, 0xF1, 0x1D, 0x00, 0x40,
+
+ //
+ //Bus , Dev, Func, xHCI Device
+ 0x00 , 0x14, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+
+ //Bus , Dev, Func, LPE Device
+ 0x00 , 0x15, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, USB OTG Device
+ 0x00 , 0x16, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 DMA Device
+ 0x00 , 0x18, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 I2C0 Device
+ 0x00 , 0x18, 0x01,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 I2C1 Device
+ 0x00 , 0x18, 0x02,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 I2C2 Device
+ 0x00 , 0x18, 0x03,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 I2C3 Device
+ 0x00 , 0x18, 0x04,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 I2C4 Device
+ 0x00 , 0x18, 0x05,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 I2C5 Device
+ 0x00 , 0x18, 0x06,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO2 I2C6 Device
+ 0x00 , 0x18, 0x07,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, SEC Device
+ 0x00 , 0x1A, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+
+ //Bus , Dev, Func, HD Audio Device
+ 0x00 , 0x1B, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ //
+ //Bus , Dev, Func, SMBUS device
+ //
+ //Bus , Dev, Func, PCIe Root Port #1
+ 0x00 , 0x1C, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, PCIe Root Port #2
+ 0x00 , 0x1C, 0x01,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, PCIe Root Port #3
+ 0x00 , 0x1C, 0x02,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, PCIe Root Port #4
+ 0x00 , 0x1C, 0x03,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, VGA bus1
+ //
+ //Bus , Dev, Func, LPIO1 DMA Device
+ 0x00 , 0x1E, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO1 PWM0 Device
+ 0x00 , 0x1E, 0x01,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO1 PWM1 Device
+ 0x00 , 0x1E, 0x02,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO1 HSUART0 Device
+ 0x00 , 0x1E, 0x03,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO1 HSUART1 Device
+ 0x00 , 0x1E, 0x04,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO1 SPI Device
+ 0x00 , 0x1E, 0x05,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO1 SPI2 Device
+ 0x00 , 0x1E, 0x06,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, LPIO1 SPI3 Device
+ 0x00 , 0x1E, 0x07,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, PCU Device
+ 0x00 , 0x1F, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0x00 , 0x08, 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
+ 0x32 , 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ //
+ //Bus , Dev, Func, Bus 1 Function 0
+ 0x01 , 0x00, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0x58 , 0x93, 0x18, 0x01, 0xb0, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, Bus 1 Function 1
+ 0x01 , 0x00, 0x01,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, Bus 2 Function 0
+ 0x02 , 0x00, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, Bus 2 Function 1
+ 0x02 , 0x00, 0x01,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, Bus 3 Function 0
+ 0x03 , 0x00, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, Bus 3 Function 1
+ 0x03 , 0x00, 0x01,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, Bus 4 Function 0
+ 0x04 , 0x00, 0x00,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+
+ //Bus , Dev, Func, Bus 4 Function 1
+ 0x04 , 0x00, 0x01,
+ //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 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;
+}