diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Chipset/SB/SBSmm.c | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Chipset/SB/SBSmm.c')
-rw-r--r-- | Chipset/SB/SBSmm.c | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/Chipset/SB/SBSmm.c b/Chipset/SB/SBSmm.c new file mode 100644 index 0000000..1c1337a --- /dev/null +++ b/Chipset/SB/SBSmm.c @@ -0,0 +1,648 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SBSmm.c 2 3/19/13 8:20a Scottyang $ +// +// $Revision: 2 $ +// +// $Date: 3/19/13 8:20a $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SBSmm.c $ +// +// 2 3/19/13 8:20a Scottyang +// [TAG] EIP118158 +// [Category] Improvement +// [Description] Correct SBLib_CmosRead () offset. +// [Files] SmiHandlerPorting2.c, SBDxe.c, SBGeneric.c, SBSmm.c, +// SmiHandlerPorting.c +// +// 1 2/08/12 8:24a Yurenlai +// Intel Lynx Point/SB eChipset initially releases. +// +//************************************************************************* + + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: SBSMM.C +// +// Description: This file contains code for SMM control - the +// protocol defined by Framework +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + + +// Module specific Includes +#include <Efi.h> +#include <token.h> +#include <HOB.h> +#include <DXE.h> +#include <AmiLib.h> +#include <AmiDxeLib.h> +#include <AmiCspLib.h> + +// Used Protocols +#include <Protocol\PciRootBridgeIo.h> +#include <Protocol\BootScriptSave.h> +#include <Protocol\SmmAccess.h> +// Produced Protocols +#include <Protocol\SmmControl.h> +#if PI_SPECIFICATION_VERSION >= 0x0001000A +#include <Protocol\SmmControl2.h> +#endif + +// Function Prototypes +typedef struct { + UINT8 IoReg8; + UINT32 Value32; +} PMIO_BOOT_SCRIPT_STRUCT; + +EFI_STATUS +SBSMM_ClearSMI( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN BOOLEAN Periodic OPTIONAL +); + +VOID SBSMM_BootScript(); + +EFI_STATUS +SBSMM_TriggerSMI( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN OUT INT8 *ArgumentBuffer OPTIONAL, + IN OUT UINTN *ArgumentBufferSize OPTIONAL, + IN BOOLEAN Periodic OPTIONAL, + IN UINTN ActivationInterval OPTIONAL +); + +EFI_STATUS +SBSMM_GetRegisterInfo( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN OUT EFI_SMM_CONTROL_REGISTER *SmiRegister +); + +VOID SaveSmiEnBeforeBoot ( + IN EFI_EVENT Event, + IN VOID *Context +); + +#if PI_SPECIFICATION_VERSION >= 0x0001000A +EFI_STATUS SBSMM_TriggerSMI2( + IN CONST EFI_SMM_CONTROL2_PROTOCOL *This, + IN OUT UINT8 *CommandPort OPTIONAL, + IN OUT UINT8 *DataPort OPTIONAL, + IN BOOLEAN Periodic OPTIONAL, + IN UINTN ActivationInterval OPTIONAL +); + +EFI_STATUS SBSMM_ClearSMI2( + IN CONST EFI_SMM_CONTROL2_PROTOCOL *This, + IN BOOLEAN Periodic OPTIONAL +); +#endif + +// GUID Definitions +EFI_GUID gEfiSmmAccessProtocolGuid = EFI_SMM_ACCESS_PROTOCOL_GUID; +EFI_GUID gEfiSmmControlProtocolGuid = EFI_SMM_CONTROL_PROTOCOL_GUID; + + +// Global variable declarations +//-extern EFI_BOOT_SCRIPT_SAVE_PROTOCOL *gBootScriptSave; +EFI_SMM_ACCESS_PROTOCOL *gSmmAccess; +EFI_SMM_CONTROL_PROTOCOL mEfiSmmControlProtocol = +{ + SBSMM_TriggerSMI, + SBSMM_ClearSMI, + SBSMM_GetRegisterInfo, + 0 +}; + +EFI_SMM_CONTROL_PROTOCOL *gEfiSmmControlProtocol = NULL; + +#if PI_SPECIFICATION_VERSION >= 0x0001000A +EFI_SMM_CONTROL2_PROTOCOL gEfiSmmControl2Protocol = +{ + SBSMM_TriggerSMI2, + SBSMM_ClearSMI2, + 0 +}; +#endif + +// Portable Constants + +// Function Definition + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SBSMM_EnableSWSmi +// +// Description: This function programs the SB chipset registers to enable +// S/W SMI generation +// +// Input: None +// +// Output: EFI_SUCCESS Always +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SBSMM_EnableSWSmi(VOID) +{ +/* + UINT32 Value32; + + SBSMM_ClearSMI(&mEfiSmmControlProtocol, FALSE); + SBSMM_BootScript(); + +//Porting Required. Include code to enable S/W SMI generation + Value32 = IoRead32(PM_BASE_ADDRESS + ICH_IOREG_SMI_EN) | (BIT05 | BIT00); + IoWrite32(PM_BASE_ADDRESS + ICH_IOREG_SMI_EN, Value32); //Enable global SMIs. + + Value32 = 0x00002002B; + BOOT_SCRIPT_S3_IO_WRITE_MACRO(gBootScriptSave, + EfiBootScriptWidthUint32, + PM_BASE_ADDRESS + ICH_IOREG_SMI_EN, + 1, + &Value32); +//End Porting +*/ + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SBSMM_TriggerSMI +// +// Description: This function generates a software SMI by writing the provided +// byte value into the software SMI generation register +// +// Input: *This Pointer to the SMM control protocol +// *ArgumentBuffer Contains the value to be written to the +// S/W SMI port. Currently supports byte only +// and this is a optional pointer +// *ArgumentBufferSize Optional. Valid value is 1 +// Periodic Boolean indicating the nature of generation +// TRUE means periodic generation depending on +// timing value provided in the next variable +// CURRENTLY NOT SUPPORTED. EXPECTS FALSE +// ActivationInterval Optional. NOT SUPPORTED +// +// Output: EFI_STATUS +// EFI_SUCCESS S/W SMI triggered successfully +// EFI_INVALID_PARAMETER If Periodic is TRUE or when +// (ArgumentBuffer is not NULL and +// ArgumentBufferSize is not 1) +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +// Here is the control flow of this function: +// 1. If Periodic was TRUE, return EFI_INVALID_PARAMETER. +// 2. If ArgumentBuffer == NULL, use 0xFF as data. +// 3. If not NULL, if valid byte, use it as data. Otherwise +// return EFI_INVALID_PARAMETER. +// 4. Deactive any active SMI status. +// 5. Write the data to the SMI trigger port. +// 6. Return EFI_SUCCESS. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SBSMM_TriggerSMI( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN OUT INT8 *ArgumentBuffer OPTIONAL, + IN OUT UINTN *ArgumentBufferSize OPTIONAL, + IN BOOLEAN Periodic OPTIONAL, + IN UINTN ActivationInterval OPTIONAL +) +{ + UINT8 Data; + EFI_STATUS Status = EFI_SUCCESS; + + if (Periodic) + return EFI_INVALID_PARAMETER; + + if (ArgumentBuffer == NULL) + { + Data = 0xFF; // If no data given, use 0xFF to trigger SMI. + } + else + { + if (ArgumentBufferSize == NULL || *ArgumentBufferSize != 1) + return EFI_INVALID_PARAMETER; // Only able to send 1 byte. + Data = *ArgumentBuffer; + } + + // Porting Required. Include code to generate S/W SMI + WRITE_IO32_PM(ICH_IOREG_SMI_EN, (READ_IO32_PM(ICH_IOREG_SMI_EN) | (BIT5 | BIT0))); + WRITE_IO8(SW_SMI_IO_ADDRESS, Data); // This triggers SMI + // Porting End + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SBSMM_ClearSMI +// +// Description: This function clears all SMI status registers and generates +// End-of-SMI (EOS) +// +// Input: *This Pointer to the SMM control protocol +// Periodic Boolean indicating the nature of clearing +// TRUE means periodic SMI clearing +// CURRENTLY NOT SUPPORTED. EXPECTS FALSE +// +// Output: EFI_STATUS +// EFI_SUCCESS SMI status successfully cleared +// EFI_INVALID_PARAMETER If Periodic is TRUE +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +// Here is the control flow of this function: +// 1. If Periodic was TRUE, return EFI_INVALID_PARAMETER. +// 2. Clear SMI Status on all appropriate SMI status registers +// 3. Set EOS. +// 4. Return EFI_SUCCESS. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SBSMM_ClearSMI( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN BOOLEAN Periodic OPTIONAL +) +{ + + if (Periodic) return EFI_INVALID_PARAMETER; + + // Porting Required. Include code to clear software SMI status only + WRITE_IO8_PM(ICH_IOREG_SMI_STS, 0x20); // 0x34 + + + //Set EOS + SET_IO8_PM(ICH_IOREG_SMI_EN, BIT01); + + // Porting end + + return EFI_SUCCESS; +} + +#if PI_SPECIFICATION_VERSION >= 0x0001000A +EFI_STATUS SBSMM_TriggerSMI2( + IN CONST EFI_SMM_CONTROL2_PROTOCOL *This, + IN OUT UINT8 *CommandPort OPTIONAL, + IN OUT UINT8 *DataPort OPTIONAL, + IN BOOLEAN Periodic OPTIONAL, + IN UINTN ActivationInterval OPTIONAL +) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN DataSize = 1; + UINT8 Data; + + if (Periodic) + return EFI_INVALID_PARAMETER; + + if (CommandPort == NULL) + { + Data = 0xFF; // If no data given, use 0xFF to trigger SMI. + } + else + { + Data = *CommandPort; + } + + Status = gEfiSmmControlProtocol->Trigger(gEfiSmmControlProtocol, &Data, &DataSize, FALSE, 0); + + return Status; +} + +EFI_STATUS SBSMM_ClearSMI2( + IN CONST EFI_SMM_CONTROL2_PROTOCOL *This, + IN BOOLEAN Periodic OPTIONAL +) +{ + if (Periodic) + return EFI_INVALID_PARAMETER; + + gEfiSmmControlProtocol->Clear(gEfiSmmControlProtocol, FALSE); + + return EFI_SUCCESS; +} +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SBSMM_BootScript +// +// Description: This function clears all SMI enables registers and generates +// End-of-SMI (EOS) in Boot Script +// +// Input: None +// +// Output: None +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SBSMM_BootScript(VOID) +{ +/* + UINT16 i; + UINT16 j; + +// 0x00-0x03 +// 0x28-0x2B +// 0x2C-0x2F +// 0x20-0x23 +// 0x24-0x27 +// 0x38-0x3B +// 0x34-0x37 + PMIO_BOOT_SCRIPT_STRUCT PMIoBootScriptTbl[] = { \ + {ICH_IOREG_PM1_STS, 0x01000831},\ + {ICH_IOREG_GPE0_EN, 0},\ + {ICH_IOREG_GPE0_EN + 4, 0},\ + {ICH_IOREG_GPE0_STS, 0xFFFFFFFF},\ + {ICH_IOREG_GPE0_STS + 4, 0xFFFFFFFF},\ + {ICH_IOREG_ALT_GP_SMI_EN + 4, 0xFFFF0000},\ + {ICH_IOREG_SMI_STS, 0xFFFFFFF}}; + + // Use boot script to do : + // 1. Clear PM1 statuses except power button & RTC statuses and + // enable power button, OS will setup it as a wake event anyway. + // 2. disable GPE enables. + // 3. disable SMI enables and clear SMI statuses. + // 4. Enable SCI (SCI_EN). + + j = sizeof(PMIoBootScriptTbl) / sizeof(PMIO_BOOT_SCRIPT_STRUCT); + for (i = 0; i < j; i++) + BOOT_SCRIPT_S3_IO_WRITE_MACRO( \ + gBootScriptSave, \ + EfiBootScriptWidthUint32, \ + PM_BASE_ADDRESS + PMIoBootScriptTbl[i].IoReg8,\ + 1, \ + &PMIoBootScriptTbl[i].Value32 ); + + + // Enable SCI. + i = 1; + j = 0xffff; + BOOT_SCRIPT_S3_IO_READ_WRITE_MACRO( \ + gBootScriptSave, \ + EfiBootScriptWidthUint16, \ + PM_BASE_ADDRESS + ICH_IOREG_PM1_CNT, + &i, \ + &j ); +*/ +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SaveSmiEnBeforeBoot +// +// Description: This function uses boot script to all SMI enables before boot +// to OS. +// +// Input: Event - Event of callback +// Context - Context of callback. +// +// Output: None +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SaveSmiEnBeforeBoot ( + IN EFI_EVENT Event, + IN VOID *Context ) +{ +/* + // Porting Required. + UINT32 Buffer32; + UINT32 PCIAdd; + UINT8 Data8; + + // Remove SLP_SMI from boot script if needed. + Buffer32 = READ_IO32_PM(ICH_IOREG_SMI_EN) & ~(BIT04 | BIT06); + + BOOT_SCRIPT_S3_IO_WRITE_MACRO( \ + gBootScriptSave, \ + EfiBootScriptWidthUint32, \ + PM_BASE_ADDRESS + ICH_IOREG_SMI_EN, \ + 1, \ + &Buffer32 ); + + + // Save NMI2SMI_EN, TCO_TMR_HLT and TCO_LOCK + Data8 = READ_IO8_TCO(ICH_IOREG_TCO1_CNT + 1) & (BIT01 | BIT03 | BIT04); + BOOT_SCRIPT_S3_IO_WRITE_MACRO( \ + gBootScriptSave, \ + EfiBootScriptWidthUint8, \ + TCO_BASE_ADDRESS + ICH_IOREG_TCO1_CNT + 1, \ + 1, \ + &Data8 ); + + + PCIAdd = EFI_SB_PCI_CFG_ADDRESS(LPC_BUS, LPC_DEVICE, LPC_FUNC, ICH_REG_LPC_VID); + + Data8 = READ_PCI8_SB(ICH_REG_GEN_PMCON_1); + BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO( \ + gBootScriptSave, \ + EfiPciIoWidthUint8, \ + EFI_SB_PCI_CFG_ADDRESS(LPC_BUS, LPC_DEVICE, LPC_FUNC, ICH_REG_GEN_PMCON_1), \ + 1, \ + &Data8 + ); + + Data8 = READ_PCI8_SB(ICH_REG_GEN_PMCON_3); + Data8 &= ~(BIT01); + BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO( \ + gBootScriptSave, \ + EfiPciIoWidthUint8, \ + EFI_SB_PCI_CFG_ADDRESS(LPC_BUS, LPC_DEVICE, LPC_FUNC, ICH_REG_GEN_PMCON_3), \ + 1, \ + &Data8 + ); +*/ + + // Porting End + pBS->CloseEvent(Event); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SBSMM_GetRegisterInfo +// +// Description: This function returns the S/W SMI generation register and +// its status register values +// +// Input: *This Pointer to the SMM control protocol +// SmiRegister Pointer to the SMM control register structure +// +// Output: EFI_UNSUPPORTED +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +// 1. Return EFI_UNSUPPORTED. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SBSMM_GetRegisterInfo( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN OUT EFI_SMM_CONTROL_REGISTER *SmiRegister +) +{ + + // Porting Required. Include code to return I/O port to generate S/W SMI + SmiRegister->SmiTriggerRegister = SW_SMI_IO_ADDRESS; + SmiRegister->SmiDataRegister = SW_SMI_IO_ADDRESS + 1; + // Porting End + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: DisableAllSmi +// +// Description: This function disables all SMI's which can be caused by +// SouthBridge, include global SMI. +// +// Input: None +// +// Output: None +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID DisableAllSmi(VOID) +{ + //--WRITE_IO16_PM(ICH_IOREG_PM1_EN, 0x0000); // 0x02 + //--WRITE_IO32_PM(ICH_IOREG_GPE0_EN, 0x00000000); // 0x2C + //--WRITE_IO32_PM(ICH_IOREG_SMI_EN, 0x00000000); // 0x30 + //--WRITE_IO32_PM(ICH_IOREG_ALT_GP_SMI_EN, 0x00000000); // 0x38 +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SBSMM_Init +// +// Description: This function is invoked from SB DXE to initialize SMM +// related stuff in NorthBridge and install appropriate +// SMM protocols such as SMM Access & SMM Control +// +// Input: ImageHandle Image handle +// SystemTable Pointer to the system table +// +// Output: Return Status based on errors that occurred while waiting for +// time to expire. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SbSmmInit( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_STATUS Status; + EFI_EVENT mEvent; + UINT8 Value; + + PROGRESS_CODE(DXE_SB_SMM_INIT); + + Status = pBS->LocateProtocol(&gEfiSmmControlProtocolGuid, NULL, &gEfiSmmControlProtocol); + if (EFI_ERROR(Status)) + { + Status = pBS->LocateProtocol(&gEfiSmmAccessProtocolGuid, NULL, &gSmmAccess); + ASSERT_EFI_ERROR(Status); + + // Disable all SMI enables here + DisableAllSmi(); + + //Must read RTC Reg C to be able to clear SMM RTC alarm flag. + Value = SBLib_CmosRead(0x0C); + + // Clear all SMI status here. + //--WRITE_IO16_PM(ICH_IOREG_PM1_STS, 0xCF31); // 0x00 + //--WRITE_IO32_PM(ICH_IOREG_GPE0_STS, 0xFFFFFFFF); // 0x20 + //--WRITE_IO32_PM(ICH_IOREG_GPE0_STS + 4, 0xffffffff); // 0x24 + //--WRITE_IO16_PM(ICH_IOREG_ALT_GP_SMI_STS, 0xFFFF); // 0x3A + //--WRITE_IO16_PM(ICH_IOREG_DEVACT_STS, 0xFFFF); // 0x44 + //--WRITE_IO16_TCO(ICH_IOREG_TCO1_STS, 0xFFFF); // 0x04 + //--WRITE_IO16_TCO(ICH_IOREG_TCO2_STS, (0xFFFF)); // 0x06 + //--WRITE_IO32_PM(ICH_IOREG_SMI_STS, 0xFFFFFFFF); // 0x34 + + // Enable S/W SMI Generation + SBSMM_EnableSWSmi(); + + Status = CreateReadyToBootEvent( TPL_NOTIFY, \ + SaveSmiEnBeforeBoot, \ + NULL, \ + &mEvent ); + ASSERT_EFI_ERROR(Status); + + Status = pBS->InstallMultipleProtocolInterfaces( + &TheImageHandle, + &gEfiSmmControlProtocolGuid, + &mEfiSmmControlProtocol, +#if PI_SPECIFICATION_VERSION >= 0x0001000A + &gEfiSmmControl2ProtocolGuid, + &gEfiSmmControl2Protocol, +#endif + NULL, + NULL + ); + ASSERT_EFI_ERROR(Status); + } + else + { +#if PI_SPECIFICATION_VERSION >= 0x0001000A + Status = pBS->InstallMultipleProtocolInterfaces( + &TheImageHandle, + &gEfiSmmControl2ProtocolGuid, + &gEfiSmmControl2Protocol, + NULL, + NULL + ); + ASSERT_EFI_ERROR(Status); +#endif + } + + return Status; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* |