]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiPayloadPkg: Add a common SMM control Runtime DXE module
authorGuo Dong <guo.dong@intel.com>
Wed, 22 Sep 2021 21:22:42 +0000 (14:22 -0700)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 25 Oct 2021 17:28:21 +0000 (17:28 +0000)
This module consumes SMM Registers HOB (SMI_GBL_EN and SMI_APM_EN) to
install SMM control 2 protocol gEfiSmmControl2ProtocolGuid.
The protocol activate() would set SMI_GBL_EN and SMI_APM_EN and trigger
SMI by writing to IO port 0xB3 and 0xB2.

Signed-off-by: Guo Dong <guo.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Benjamin You <benjamin.you@intel.com>
UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h [new file with mode: 0644]
UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c [new file with mode: 0644]
UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.inf [new file with mode: 0644]
UefiPayloadPkg/UefiPayloadPkg.dec

diff --git a/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h b/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h
new file mode 100644 (file)
index 0000000..8a1d3d7
--- /dev/null
@@ -0,0 +1,48 @@
+/** @file\r
+  This file defines the SMM info hob structure.\r
+\r
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef PAYLOAD_SMM_REGISTER_INFO_GUID_H_\r
+#define PAYLOAD_SMM_REGISTER_INFO_GUID_H_\r
+\r
+#include <IndustryStandard/Acpi.h>\r
+\r
+///\r
+/// SMM Information GUID\r
+///\r
+extern EFI_GUID gSmmRegisterInfoGuid;\r
+\r
+///\r
+/// Reuse ACPI definition\r
+/// AddressSpaceId(0xC0-0xFF) is defined by OEM for MSR and other spaces\r
+///\r
+typedef EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE  PLD_GENERIC_ADDRESS;\r
+\r
+#define REGISTER_ID_SMI_GBL_EN         1\r
+#define REGISTER_ID_SMI_GBL_EN_LOCK    2\r
+#define REGISTER_ID_SMI_EOS            3\r
+#define REGISTER_ID_SMI_APM_EN         4\r
+#define REGISTER_ID_SMI_APM_STS        5\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  UINT64                Id;\r
+  UINT64                Value;\r
+  PLD_GENERIC_ADDRESS   Address;\r
+} PLD_GENERIC_REGISTER;\r
+\r
+typedef struct {\r
+  UINT16                Revision;\r
+  UINT16                Reserved;\r
+  UINT32                Count;\r
+  PLD_GENERIC_REGISTER  Registers[0];\r
+} PLD_SMM_REGISTERS;\r
+\r
+\r
+#pragma pack()\r
+\r
+#endif\r
diff --git a/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c b/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c
new file mode 100644 (file)
index 0000000..6dd91e2
--- /dev/null
@@ -0,0 +1,256 @@
+/** @file\r
+  This module produces the SMM Control2 Protocol\r
+\r
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/SmmControl2.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Guid/SmmRegisterInfoGuid.h>\r
+\r
+#define SMM_DATA_PORT       0xB3\r
+#define SMM_CONTROL_PORT    0xB2\r
+\r
+typedef struct {\r
+  UINT8   GblBitOffset;\r
+  UINT8   ApmBitOffset;\r
+  UINT32  Address;\r
+} SMM_CONTROL2_REG;\r
+\r
+SMM_CONTROL2_REG        mSmiCtrlReg;\r
+\r
+/**\r
+  Invokes SMI activation from either the preboot or runtime environment.\r
+\r
+  This function generates an SMI.\r
+\r
+  @param[in]     This                The EFI_SMM_CONTROL2_PROTOCOL instance.\r
+  @param[in,out] CommandPort         The value written to the command port.\r
+  @param[in,out] DataPort            The value written to the data port.\r
+  @param[in]     Periodic            Optional mechanism to engender a periodic stream.\r
+  @param[in]     ActivationInterval  Optional parameter to repeat at this period one\r
+                                     time or, if the Periodic Boolean is set, periodically.\r
+\r
+  @retval EFI_SUCCESS            The SMI has been engendered.\r
+  @retval EFI_DEVICE_ERROR       The timing is unsupported.\r
+  @retval EFI_INVALID_PARAMETER  The activation period is unsupported.\r
+  @retval EFI_INVALID_PARAMETER  The last periodic activation has not been cleared.\r
+  @retval EFI_NOT_STARTED        The MM base service has not been initialized.\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
+  UINT32                                 SmiEn;\r
+  UINT32                                 SmiEnableBits;\r
+\r
+  if (Periodic) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  SmiEn         = IoRead32 (mSmiCtrlReg.Address);\r
+  SmiEnableBits = (1 << mSmiCtrlReg.GblBitOffset) | (1 << mSmiCtrlReg.ApmBitOffset);\r
+  if ((SmiEn & SmiEnableBits) != SmiEnableBits) {\r
+    //\r
+    // Set the "global SMI enable" bit and APM bit\r
+    //\r
+    IoWrite32 (mSmiCtrlReg.Address, SmiEn | SmiEnableBits);\r
+  }\r
+\r
+  IoWrite8 (SMM_DATA_PORT,    DataPort    == NULL ? 0 : *DataPort);\r
+  IoWrite8 (SMM_CONTROL_PORT, CommandPort == NULL ? 0 : *CommandPort);\r
+  return EFI_SUCCESS;\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\r
+  )\r
+{\r
+  if (Periodic) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Temporarily do nothing here\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+///\r
+/// SMM COntrol2 Protocol instance\r
+///\r
+EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {\r
+  Activate,\r
+  Deactivate,\r
+  0\r
+};\r
+\r
+/**\r
+  Get specified SMI register based on given register ID\r
+\r
+  @param[in]  SmmRegister  SMI related register array from bootloader\r
+  @param[in]  Id           The register ID to get.\r
+\r
+  @retval NULL             The register is not found or the format is not expected.\r
+  @return smi register\r
+\r
+**/\r
+PLD_GENERIC_REGISTER *\r
+GetSmmCtrlRegById (\r
+  IN PLD_SMM_REGISTERS    *SmmRegister,\r
+  IN UINT32               Id\r
+  )\r
+{\r
+  UINT32                  Index;\r
+  PLD_GENERIC_REGISTER    *PldReg;\r
+\r
+  PldReg = NULL;\r
+  for (Index = 0; Index < SmmRegister->Count; Index++) {\r
+    if (SmmRegister->Registers[Index].Id == Id) {\r
+      PldReg = &SmmRegister->Registers[Index];\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (PldReg == NULL) {\r
+    DEBUG ((DEBUG_INFO, "Register %d not found.\n", Id));\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Checking the register if it is expected.\r
+  //\r
+  if ((PldReg->Address.AccessSize       != EFI_ACPI_3_0_DWORD) ||\r
+      (PldReg->Address.Address          == 0) ||\r
+      (PldReg->Address.RegisterBitWidth != 1) ||\r
+      (PldReg->Address.AddressSpaceId   != EFI_ACPI_3_0_SYSTEM_IO) ||\r
+      (PldReg->Value != 1)) {\r
+    DEBUG ((DEBUG_INFO, "Unexpected SMM register.\n"));\r
+    DEBUG ((DEBUG_INFO, "AddressSpaceId= 0x%x\n", PldReg->Address.AddressSpaceId));\r
+    DEBUG ((DEBUG_INFO, "RegBitWidth   = 0x%x\n", PldReg->Address.RegisterBitWidth));\r
+    DEBUG ((DEBUG_INFO, "RegBitOffset  = 0x%x\n", PldReg->Address.RegisterBitOffset));\r
+    DEBUG ((DEBUG_INFO, "AccessSize    = 0x%x\n", PldReg->Address.AccessSize));\r
+    DEBUG ((DEBUG_INFO, "Address       = 0x%lx\n",PldReg->Address.Address ));\r
+    return NULL;\r
+  }\r
+  return PldReg;\r
+}\r
+\r
+\r
+/**\r
+  Fixup data pointers so that the services can be called in virtual mode.\r
+\r
+  @param[in] Event                The event registered.\r
+  @param[in] Context              Event context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmControlVirtualAddressChangeEvent (\r
+  IN EFI_EVENT                  Event,\r
+  IN VOID                       *Context\r
+  )\r
+{\r
+  EfiConvertPointer (0x0, (VOID **) &(mSmmControl2.Trigger));\r
+  EfiConvertPointer (0x0, (VOID **) &(mSmmControl2.Clear));\r
+}\r
+\r
+\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
+EFIAPI\r
+SmmControlEntryPoint (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_HOB_GUID_TYPE       *GuidHob;\r
+  PLD_SMM_REGISTERS       *SmmRegister;\r
+  PLD_GENERIC_REGISTER    *SmiGblEnReg;\r
+  PLD_GENERIC_REGISTER    *SmiApmEnReg;\r
+  EFI_EVENT               Event;\r
+\r
+  GuidHob = GetFirstGuidHob (&gSmmRegisterInfoGuid);\r
+  if (GuidHob == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  SmmRegister = (PLD_SMM_REGISTERS *) (GET_GUID_HOB_DATA(GuidHob));\r
+  SmiGblEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_GBL_EN);\r
+  if (SmiGblEnReg == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "SMI global enable reg not found.\n"));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  mSmiCtrlReg.Address      = (UINT32)SmiGblEnReg->Address.Address;\r
+  mSmiCtrlReg.GblBitOffset = SmiGblEnReg->Address.RegisterBitOffset;\r
+\r
+  SmiApmEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_APM_EN);\r
+  if (SmiApmEnReg == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "SMI APM enable reg not found.\n"));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (SmiApmEnReg->Address.Address != mSmiCtrlReg.Address) {\r
+    DEBUG ((DEBUG_ERROR, "SMI APM EN and SMI GBL EN are expected to have same register base\n"));\r
+    DEBUG ((DEBUG_ERROR, "APM:0x%x, GBL:0x%x\n", SmiApmEnReg->Address.Address, mSmiCtrlReg.Address));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  mSmiCtrlReg.ApmBitOffset = SmiApmEnReg->Address.RegisterBitOffset;\r
+\r
+  //\r
+  // Install our protocol interfaces on the device's handle\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ImageHandle,\r
+                  &gEfiSmmControl2ProtocolGuid,\r
+                  &mSmmControl2,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  SmmControlVirtualAddressChangeEvent,\r
+                  NULL,\r
+                  &gEfiEventVirtualAddressChangeGuid,\r
+                  &Event\r
+                  );\r
+  return Status;\r
+}\r
diff --git a/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.inf b/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.inf
new file mode 100644 (file)
index 0000000..f0c2a45
--- /dev/null
@@ -0,0 +1,50 @@
+## @file\r
+# SMM Control runtime DXE Module\r
+#\r
+# Provides the ability to generate a software SMI.\r
+#\r
+#  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+#\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SmmControlRuntimeDxe\r
+  FILE_GUID                      = C3099578-F815-4a96-84A3-FC593760181D\r
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SmmControlEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  SmmControlRuntimeDxe.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiPayloadPkg/UefiPayloadPkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  DebugLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeLib\r
+  PcdLib\r
+  IoLib\r
+  HobLib\r
+\r
+[Guids]\r
+  gSmmRegisterInfoGuid\r
+  gEfiEventVirtualAddressChangeGuid\r
+\r
+[Protocols]\r
+  gEfiSmmControl2ProtocolGuid             ## PRODUCES\r
+\r
+[Depex]\r
+  TRUE\r
index e5e8db8863d6413b22fc662f180e1d1e22718127..4f93d3e671fa27fe90e10c6b2c7a16ec6a485342 100644 (file)
@@ -37,6 +37,8 @@
   gUefiSerialPortInfoGuid  = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1 } }\r
   gLoaderMemoryMapInfoGuid = { 0xa1ff7424, 0x7a1a, 0x478e, { 0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32 } }\r
 \r
+  gSmmRegisterInfoGuid     = { 0xaa9bd7a7, 0xcafb, 0x4499, { 0xa4, 0xa9, 0xb, 0x34, 0x6b, 0x40, 0xa6, 0x22 } }\r
+\r
 [Ppis]\r
   gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} }\r
 \r