+++ /dev/null
-/** @file\r
-This module produces the SMM COntrol2 Protocol for QNC\r
-\r
-Copyright (c) 2013-2015 Intel Corporation.\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <PiDxe.h>\r
-#include <Protocol/SmmControl2.h>\r
-#include <IndustryStandard/Pci.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PciLib.h>\r
-#include <IntelQNCDxe.h>\r
-#include <Library/QNCAccessLib.h>\r
-#include <Uefi/UefiBaseType.h>\r
-\r
-#define EFI_INTERNAL_POINTER 0x00000004\r
-\r
-extern EFI_GUID gEfiEventVirtualAddressChangeGuid;\r
-\r
-/**\r
- Generates an SMI using the parameters passed in.\r
-\r
- @param This A pointer to an instance of\r
- EFI_SMM_CONTROL2_PROTOCOL\r
- @param ArgumentBuffer The argument buffer\r
- @param ArgumentBufferSize The size of the argument buffer\r
- @param Periodic TRUE to indicate a periodical SMI\r
- @param ActivationInterval Interval of the periodical SMI\r
-\r
- @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1\r
- @return Return value from SmmTrigger().\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Activate (\r
- IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,\r
- IN OUT UINT8 *CommandPort OPTIONAL,\r
- IN OUT UINT8 *DataPort OPTIONAL,\r
- IN BOOLEAN Periodic OPTIONAL,\r
- IN EFI_SMM_PERIOD ActivationInterval OPTIONAL\r
- );\r
-\r
-/**\r
- Clears an SMI.\r
-\r
- @param This Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL\r
- @param Periodic TRUE to indicate a periodical SMI\r
-\r
- @return Return value from SmmClear()\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Deactivate (\r
- IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,\r
- IN BOOLEAN Periodic OPTIONAL\r
- );\r
-\r
-///\r
-/// Handle for the SMM Control2 Protocol\r
-///\r
-EFI_HANDLE mSmmControl2Handle = NULL;\r
-\r
-///\r
-/// SMM COntrol2 Protocol instance\r
-///\r
-EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {\r
- Activate,\r
- Deactivate,\r
- 0\r
-};\r
-\r
-VOID\r
-EFIAPI\r
-SmmControlVirtualddressChangeEvent (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Fixup internal data pointers so that the services can be called in virtual mode.\r
-\r
-Arguments:\r
-\r
- Event The event registered.\r
- Context Event context.\r
-\r
-Returns:\r
-\r
- None.\r
-\r
---*/\r
-{\r
- gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Trigger));\r
- gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Clear));\r
-}\r
-\r
-/**\r
- Clear SMI related chipset status and re-enable SMI by setting the EOS bit.\r
-\r
- @retval EFI_SUCCESS The requested operation has been carried out successfully\r
- @retval EFI_DEVICE_ERROR The EOS bit could not be set.\r
-\r
-**/\r
-EFI_STATUS\r
-SmmClear (\r
- VOID\r
- )\r
-{\r
- UINT16 GPE0BLK_Base;\r
-\r
- //\r
- // Get GPE0BLK_Base\r
- //\r
- GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
-\r
- //\r
- // Clear the Power Button Override Status Bit, it gates EOS from being set.\r
- // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.\r
- //\r
-\r
- //\r
- // Clear the APM SMI Status Bit\r
- //\r
- IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);\r
-\r
- //\r
- // Set the EOS Bit\r
- //\r
- IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Generates an SMI using the parameters passed in.\r
-\r
- @param This A pointer to an instance of\r
- EFI_SMM_CONTROL_PROTOCOL\r
- @param ArgumentBuffer The argument buffer\r
- @param ArgumentBufferSize The size of the argument buffer\r
- @param Periodic TRUE to indicate a periodical SMI\r
- @param ActivationInterval Interval of the periodical SMI\r
-\r
- @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1\r
- @retval EFI_SUCCESS SMI generated\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Activate (\r
- IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,\r
- IN OUT UINT8 *CommandPort OPTIONAL,\r
- IN OUT UINT8 *DataPort OPTIONAL,\r
- IN BOOLEAN Periodic OPTIONAL,\r
- IN EFI_SMM_PERIOD ActivationInterval OPTIONAL\r
- )\r
-{\r
- UINT16 GPE0BLK_Base;\r
- UINT32 NewValue;\r
-\r
- //\r
- // Get GPE0BLK_Base\r
- //\r
- GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
-\r
- if (Periodic) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Clear any pending the APM SMI\r
- //\r
- if (EFI_ERROR (SmmClear())) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // Enable the APMC SMI\r
- //\r
- IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM);\r
-\r
- //\r
- // Enable SMI globally\r
- //\r
- NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
- NewValue |= SMI_EN;\r
- QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
-\r
-\r
- //\r
- // Set APMC_STS\r
- //\r
- if (DataPort == NULL) {\r
- IoWrite8 (PcdGet16 (PcdSmmDataPort), 0xFF);\r
- } else {\r
- IoWrite8 (PcdGet16 (PcdSmmDataPort), *DataPort);\r
- }\r
-\r
- //\r
- // Generate the APMC SMI\r
- //\r
- if (CommandPort == NULL) {\r
- IoWrite8 (PcdGet16 (PcdSmmActivationPort), 0xFF);\r
- } else {\r
- IoWrite8 (PcdGet16 (PcdSmmActivationPort), *CommandPort);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Clears an SMI.\r
-\r
- @param This Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL\r
- @param Periodic TRUE to indicate a periodical SMI\r
-\r
- @return Return value from SmmClear()\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Deactivate (\r
- IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,\r
- IN BOOLEAN Periodic\r
- )\r
-{\r
- if (Periodic) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return SmmClear();\r
-}\r
-\r
-/**\r
- This is the constructor for the SMM Control protocol.\r
-\r
- This function installs EFI_SMM_CONTROL2_PROTOCOL.\r
-\r
- @param ImageHandle Handle for the image of this driver\r
- @param SystemTable Pointer to the EFI System Table\r
-\r
- @retval EFI_UNSUPPORTED There's no Intel ICH on this platform\r
- @return The status returned from InstallProtocolInterface().\r
-\r
---*/\r
-EFI_STATUS\r
-SmmControl2Init (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_EVENT Event;\r
- UINT16 PM1BLK_Base;\r
- UINT16 GPE0BLK_Base;\r
- BOOLEAN SciEn;\r
- UINT32 NewValue;\r
-\r
- //\r
- // Get PM1BLK_Base & GPE0BLK_Base\r
- //\r
- PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);\r
- GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
-\r
- //\r
- // Install our protocol interfaces on the device's handle\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mSmmControl2Handle,\r
- &gEfiSmmControl2ProtocolGuid, &mSmmControl2,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Determine whether an ACPI OS is present (via the SCI_EN bit)\r
- //\r
- SciEn = (BOOLEAN)((IoRead16 (PM1BLK_Base + R_QNC_PM1BLK_PM1C) & B_QNC_PM1BLK_PM1C_SCIEN) != 0);\r
- if (!SciEn) {\r
- //\r
- // Clear any SMIs that double as SCIs (when SCI_EN==0)\r
- //\r
- IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1S), B_QNC_PM1BLK_PM1S_ALL);\r
- IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1E), 0x00000000);\r
- IoWrite32 ((PM1BLK_Base + R_QNC_PM1BLK_PM1C), 0x00000000);\r
- IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0S), B_QNC_GPE0BLK_GPE0S_ALL);\r
- IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0E), 0x00000000);\r
- }\r
-\r
- //\r
- // Clear and disable all SMIs that are unaffected by SCI_EN\r
- // Set EOS\r
- //\r
- IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), 0x00000000);\r
- IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), (B_QNC_GPE0BLK_SMIS_EOS + B_QNC_GPE0BLK_SMIS_ALL));\r
-\r
- //\r
- // Enable SMI globally\r
- //\r
- NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
- NewValue |= SMI_EN;\r
- QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
-\r
- //\r
- // Make sure to write this register last -- EOS re-enables SMIs for the QNC\r
- //\r
- IoAndThenOr32 (\r
- GPE0BLK_Base + R_QNC_GPE0BLK_SMIE,\r
- (UINT32)(~B_QNC_GPE0BLK_SMIE_ALL),\r
- B_QNC_GPE0BLK_SMIE_APM\r
- );\r
-\r
- //\r
- // Make sure EOS bit cleared\r
- //\r
- DEBUG_CODE_BEGIN ();\r
- if (IoRead32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS) & B_QNC_GPE0BLK_SMIS_EOS) {\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "******************************************************************************\n"\r
- "BIG ERROR: SmmControl constructor couldn't properly initialize the ACPI table.\n"\r
- " SmmControl->Clear will probably hang. \n"\r
- " NOTE: SCI_EN = %d \n"\r
- "******************************************************************************\n",\r
- SciEn\r
- ));\r
-\r
- //\r
- // If we want the system to stop, then keep the ASSERT(FALSE).\r
- // Otherwise, comment it out.\r
- //\r
- ASSERT (FALSE);\r
- }\r
- DEBUG_CODE_END ();\r
-\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- SmmControlVirtualddressChangeEvent,\r
- NULL,\r
- &gEfiEventVirtualAddressChangeGuid,\r
- &Event\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r