]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Library / QNCSmmLib / QNCSmmLib.c
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
new file mode 100644 (file)
index 0000000..6ddc099
--- /dev/null
@@ -0,0 +1,322 @@
+/** @file\r
+QNC Smm Library Services that implements SMM Region access, S/W SMI generation and detection.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <Base.h>\r
+#include <IntelQNCRegs.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+#define BOOT_SERVICE_SOFTWARE_SMI_DATA          0\r
+#define RUNTIME_SOFTWARE_SMI_DATA               1\r
+\r
+/**\r
+  Triggers a run time or boot time SMI.\r
+\r
+  This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.\r
+\r
+  @param  Data                 The value to set the APMC status.\r
+\r
+**/\r
+VOID\r
+InternalTriggerSmi (\r
+  IN UINT8                     Data\r
+  )\r
+{\r
+  UINT16        PM1BLK_Base;\r
+  UINT16        GPE0BLK_Base;\r
+  UINT32        NewValue;\r
+\r
+  //\r
+  // Get PM1BLK_Base & GPE0BLK_Base\r
+  //\r
+  PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);\r
+  GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
+\r
+\r
+  //\r
+  // Enable APM 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
+  // Set APM_STS\r
+  //\r
+  IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);\r
+\r
+  //\r
+  // Generate the APM SMI\r
+  //\r
+  IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));\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
+\r
+\r
+/**\r
+  Triggers an SMI at boot time.\r
+\r
+  This function triggers a software SMM interrupt at boot time.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TriggerBootServiceSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+/**\r
+  Triggers an SMI at run time.\r
+\r
+  This function triggers a software SMM interrupt at run time.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TriggerRuntimeSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+/**\r
+  Gets the software SMI data.\r
+\r
+  This function tests if a software SMM interrupt happens. If a software SMI happens,\r
+  it retrieves the SMM data and returns it as a non-negative value; otherwise a negative\r
+  value is returned.\r
+\r
+  @return Data                 The data retrieved from SMM data port in case of a software SMI;\r
+                               otherwise a negative value.\r
+\r
+**/\r
+INTN\r
+InternalGetSwSmiData (\r
+  VOID\r
+  )\r
+{\r
+  UINT8                        SmiStatus;\r
+  UINT8                        Data;\r
+\r
+  SmiStatus = IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);\r
+  if (((SmiStatus & B_QNC_GPE0BLK_SMIS_APM) != 0) &&\r
+       (IoRead8 (PcdGet16 (PcdSmmActivationPort)) == PcdGet8 (PcdSmmActivationData))) {\r
+    Data = IoRead8 (PcdGet16 (PcdSmmDataPort));\r
+    return (INTN)(UINTN)Data;\r
+  }\r
+\r
+  return -1;\r
+}\r
+\r
+\r
+/**\r
+  Test if a boot time software SMI happened.\r
+\r
+  This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
+  it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.\r
+\r
+  @retval TRUE   A software SMI triggered at boot time happened.\r
+  @retval FLASE  No software SMI happened or the software SMI was triggered at run time.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsBootServiceSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+/**\r
+  Test if a run time software SMI happened.\r
+\r
+  This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
+  it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.\r
+\r
+  @retval TRUE   A software SMI triggered at run time happened.\r
+  @retval FLASE  No software SMI happened or the software SMI was triggered at boot time.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsRuntimeSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+\r
+/**\r
+\r
+  Clear APM SMI Status Bit; Set the EOS bit.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ClearSmi (\r
+  VOID\r
+  )\r
+{\r
+\r
+  UINT16                       GPE0BLK_Base;\r
+\r
+  //\r
+  // Get GpeBase\r
+  //\r
+  GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
+\r
+  //\r
+  // Clear the APM SMI Status Bit\r
+  //\r
+  IoOr16 (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
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "open" a region of SMRAM.\r
+  The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
+  The use of "open" means that the memory is visible from all boot-service\r
+  and SMM agents.\r
+\r
+  @retval FALSE  Cannot open a locked SMRAM region\r
+  @retval TRUE   Success to open SMRAM region.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCOpenSmramRegion (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                     Smram;\r
+\r
+  // Read the SMRAM register\r
+  Smram = QncHsmmcRead ();\r
+\r
+  //\r
+  //  Is the platform locked?\r
+  //\r
+  if (Smram & SMM_LOCKED) {\r
+    // Cannot Open a locked region\r
+    DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Open all SMRAM regions for Host access only\r
+  //\r
+  Smram |= (SMM_WRITE_OPEN | SMM_READ_OPEN);  // Open for Host.\r
+  Smram &= ~(NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN);  // Not for others.\r
+\r
+  //\r
+  // Write the SMRAM register\r
+  //\r
+  QncHsmmcWrite (Smram);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "close" a region of SMRAM.\r
+  The region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "close" means that the memory is only visible from SMM agents,\r
+  not from BS or RT code.\r
+\r
+  @retval FALSE  Cannot open a locked SMRAM region\r
+  @retval TRUE   Success to open SMRAM region.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCCloseSmramRegion (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                    Smram;\r
+\r
+  // Read the SMRAM register.\r
+  Smram = QncHsmmcRead ();\r
+\r
+  //\r
+  //  Is the platform locked?\r
+  //\r
+  if(Smram & SMM_LOCKED) {\r
+    // Cannot Open a locked region\r
+    DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  Smram &= (~(SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN));\r
+\r
+  QncHsmmcWrite (Smram);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "lock" SMRAM.\r
+  The region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "lock" means that the memory can no longer be opened\r
+  to BS state.\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCLockSmramRegion (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                    Smram;\r
+\r
+  // Read the SMRAM register.\r
+  Smram = QncHsmmcRead ();\r
+  if(Smram & SMM_LOCKED) {\r
+    DEBUG ((EFI_D_WARN, "SMRAM region already locked!\n"));\r
+  }\r
+  Smram |= SMM_LOCKED;\r
+\r
+  QncHsmmcWrite (Smram);\r
+\r
+  return;\r
+}\r