From: Guo Dong <guo.d...@intel.com>

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.d...@intel.com>
---
 .../Include/Guid/SmmRegisterInfoGuid.h        |  48 ++++
 .../SmmControlRuntimeDxe.c                    | 252 ++++++++++++++++++
 .../SmmControlRuntimeDxe.inf                  |  50 ++++
 UefiPayloadPkg/UefiPayloadPkg.dec             |   2 +
 4 files changed, 352 insertions(+)
 create mode 100644 UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h
 create mode 100644 UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c
 create mode 100644 UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.inf

diff --git a/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h 
b/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h
new file mode 100644
index 0000000000..bf908b24f2
--- /dev/null
+++ b/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h
@@ -0,0 +1,48 @@
+/** @file

+  This file defines the SMM info hob structure.

+

+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef __PAYLOAD_SMM_REGISTER_INFO_GUID_H__

+#define __PAYLOAD_SMM_REGISTER_INFO_GUID_H__

+

+#include <IndustryStandard/Acpi.h>

+

+///

+/// SMM Information GUID

+///

+extern EFI_GUID gSmmRegisterInfoGuid;

+

+///

+/// Reuse ACPI definition

+/// AddressSpaceId(0xC0�0xFF) is defined by OEM for MSR and other spaces

+///

+typedef EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE  PLD_GENERIC_ADDRESS;

+

+#define REGISTER_ID_SMI_GBL_EN         1

+#define REGISTER_ID_SMI_GBL_EN_LOCK    2

+#define REGISTER_ID_SMI_EOS            3

+#define REGISTER_ID_SMI_APM_EN         4

+#define REGISTER_ID_SMI_APM_STS        5

+

+#pragma pack(1)

+typedef struct {

+  UINT64                Id;

+  UINT64                Value;

+  PLD_GENERIC_ADDRESS   Address;

+} PLD_GENERIC_REGISTER;

+

+typedef struct {

+  UINT16                Revision;

+  UINT16                Reserved;

+  UINT32                Count;

+  PLD_GENERIC_REGISTER  Registers[0];

+} PLD_SMM_REGISTERS;

+

+

+#pragma pack()

+

+#endif

diff --git a/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c 
b/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c
new file mode 100644
index 0000000000..1558b17319
--- /dev/null
+++ b/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c
@@ -0,0 +1,252 @@
+/** @file

+  This module produces the SMM Control2 Protocol

+

+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include <PiDxe.h>

+#include <Protocol/SmmControl2.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/IoLib.h>

+#include <Library/HobLib.h>

+#include <Library/UefiRuntimeLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Guid/SmmRegisterInfoGuid.h>

+

+#define SMM_DATA_PORT       0xB3

+#define SMM_CONTROL_PORT    0xB2

+

+typedef struct {

+  UINT8   GblBitOffset;

+  UINT8   ApmBitOffset;

+  UINT32  Address;

+} SMM_CONTROL2_REG;

+

+SMM_CONTROL2_REG        mSmiCtrlReg;

+

+/**

+  Generates an SMI using the parameters passed in.

+

+  @param  This                A pointer to an instance of

+                              EFI_SMM_CONTROL_PROTOCOL

+  @param  ArgumentBuffer      The argument buffer

+  @param  ArgumentBufferSize  The size of the argument buffer

+  @param  Periodic            TRUE to indicate a periodical SMI

+  @param  ActivationInterval  Interval of the periodical SMI

+

+  @retval EFI_INVALID_PARAMETER  Periodic is TRUE or ArgumentBufferSize > 1

+  @retval EFI_SUCCESS            SMI generated

+

+**/

+EFI_STATUS

+EFIAPI

+Activate (

+  IN CONST EFI_SMM_CONTROL2_PROTOCOL     *This,

+  IN OUT  UINT8                          *CommandPort       OPTIONAL,

+  IN OUT  UINT8                          *DataPort          OPTIONAL,

+  IN      BOOLEAN                        Periodic           OPTIONAL,

+  IN      EFI_SMM_PERIOD                 ActivationInterval OPTIONAL

+  )

+{

+  UINT32                                 SmiEn;

+  UINT32                                 SmiEnableBits;

+

+  if (Periodic) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  SmiEn         = IoRead32 (mSmiCtrlReg.Address);

+  SmiEnableBits = (1 << mSmiCtrlReg.GblBitOffset) | (1 << 
mSmiCtrlReg.ApmBitOffset);

+  if ((SmiEn & SmiEnableBits) != SmiEnableBits) {

+    //

+    // Set the "global SMI enable" bit and APM bit

+    //

+    IoWrite32 (mSmiCtrlReg.Address, SmiEn | SmiEnableBits);

+  }

+

+  IoWrite8 (SMM_DATA_PORT,    DataPort    == NULL ? 0 : *DataPort);

+  IoWrite8 (SMM_CONTROL_PORT, CommandPort == NULL ? 0 : *CommandPort);

+  return EFI_SUCCESS;

+}

+

+/**

+  Clears an SMI.

+

+  @param  This      Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL

+  @param  Periodic  TRUE to indicate a periodical SMI

+

+  @return Return value from SmmClear ()

+

+**/

+EFI_STATUS

+EFIAPI

+Deactivate (

+  IN CONST EFI_SMM_CONTROL2_PROTOCOL     *This,

+  IN       BOOLEAN                       Periodic

+  )

+{

+  if (Periodic) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Temporarily do nothing here

+  //

+  return EFI_SUCCESS;

+}

+

+///

+/// SMM COntrol2 Protocol instance

+///

+EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {

+  Activate,

+  Deactivate,

+  0

+};

+

+/**

+  Get specified SMI register based on given register ID

+

+  @param[in]  SmmRegister  SMI related register array from bootloader

+  @param[in]  Id           The register ID to get.

+

+  @retval NULL             The register is not found or the format is not 
expected.

+  @return smi register

+

+**/

+PLD_GENERIC_REGISTER *

+GetSmmCtrlRegById (

+  IN PLD_SMM_REGISTERS    *SmmRegister,

+  IN UINT32               Id

+  )

+{

+  UINT32                  Index;

+  PLD_GENERIC_REGISTER    *PldReg;

+

+  PldReg = NULL;

+  for (Index = 0; Index < SmmRegister->Count; Index++) {

+    if (SmmRegister->Registers[Index].Id == Id) {

+      PldReg = &SmmRegister->Registers[Index];

+      break;

+    }

+  }

+

+  if (PldReg == NULL) {

+    DEBUG ((DEBUG_INFO, "Register %d not found.\n", Id));

+    return NULL;

+  }

+

+  //

+  // Checking the register if it is expected.

+  //

+  if ((PldReg->Address.AccessSize       != EFI_ACPI_3_0_DWORD) ||

+      (PldReg->Address.Address          == 0) ||

+      (PldReg->Address.RegisterBitWidth != 1) ||

+      (PldReg->Address.AddressSpaceId   != EFI_ACPI_3_0_SYSTEM_IO) ||

+      (PldReg->Value != 1)) {

+    DEBUG ((DEBUG_INFO, "Unexpected SMM register.\n"));

+    DEBUG ((DEBUG_INFO, "AddressSpaceId= 0x%x\n", 
PldReg->Address.AddressSpaceId));

+    DEBUG ((DEBUG_INFO, "RegBitWidth   = 0x%x\n", 
PldReg->Address.RegisterBitWidth));

+    DEBUG ((DEBUG_INFO, "RegBitOffset  = 0x%x\n", 
PldReg->Address.RegisterBitOffset));

+    DEBUG ((DEBUG_INFO, "AccessSize    = 0x%x\n", PldReg->Address.AccessSize));

+    DEBUG ((DEBUG_INFO, "Address       = 0x%lx\n",PldReg->Address.Address ));

+    return NULL;

+  }

+  return PldReg;

+}

+

+

+/**

+  Fixup data pointers so that the services can be called in virtual mode.

+

+  @param[in] Event                The event registered.

+  @param[in] Context              Event context.

+

+**/

+VOID

+EFIAPI

+SmmControlVirtualAddressChangeEvent (

+  IN EFI_EVENT                  Event,

+  IN VOID                       *Context

+  )

+{

+  EfiConvertPointer (0x0, (VOID **) &(mSmmControl2.Trigger));

+  EfiConvertPointer (0x0, (VOID **) &(mSmmControl2.Clear));

+}

+

+

+/**

+  This function installs EFI_SMM_CONTROL2_PROTOCOL.

+

+  @param  ImageHandle Handle for the image of this driver

+  @param  SystemTable Pointer to the EFI System Table

+

+  @retval EFI_UNSUPPORTED There's no Intel ICH on this platform

+  @return The status returned from InstallProtocolInterface().

+

+**/

+EFI_STATUS

+EFIAPI

+SmmControlEntryPoint (

+  IN EFI_HANDLE           ImageHandle,

+  IN EFI_SYSTEM_TABLE     *SystemTable

+  )

+{

+  EFI_STATUS              Status;

+  EFI_HOB_GUID_TYPE       *GuidHob;

+  PLD_SMM_REGISTERS       *SmmRegister;

+  PLD_GENERIC_REGISTER    *SmiGblEnReg;

+  PLD_GENERIC_REGISTER    *SmiApmEnReg;

+  EFI_EVENT               Event;

+

+  GuidHob = GetFirstGuidHob (&gSmmRegisterInfoGuid);

+  if (GuidHob == NULL) {

+    return EFI_UNSUPPORTED;

+  }

+

+  SmmRegister = (PLD_SMM_REGISTERS *) (GET_GUID_HOB_DATA(GuidHob));

+  SmiGblEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_GBL_EN);

+  if (SmiGblEnReg == NULL) {

+    DEBUG ((DEBUG_ERROR, "SMI global enable reg not found.\n"));

+    return EFI_NOT_FOUND;

+  }

+  mSmiCtrlReg.Address      = (UINT32)SmiGblEnReg->Address.Address;

+  mSmiCtrlReg.GblBitOffset = SmiGblEnReg->Address.RegisterBitOffset;

+

+  SmiApmEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_APM_EN);

+  if (SmiApmEnReg == NULL) {

+    DEBUG ((DEBUG_ERROR, "SMI APM enable reg not found.\n"));

+    return EFI_NOT_FOUND;

+  }

+

+  if (SmiApmEnReg->Address.Address != mSmiCtrlReg.Address) {

+    DEBUG ((DEBUG_ERROR, "SMI APM EN and SMI GBL EN are expected to have same 
register base\n"));

+    DEBUG ((DEBUG_ERROR, "APM:0x%x, GBL:0x%x\n", SmiApmEnReg->Address.Address, 
mSmiCtrlReg.Address));

+    return EFI_UNSUPPORTED;

+  }

+  mSmiCtrlReg.ApmBitOffset = SmiApmEnReg->Address.RegisterBitOffset;

+

+  //

+  // Install our protocol interfaces on the device's handle

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &ImageHandle,

+                  &gEfiSmmControl2ProtocolGuid,

+                  &mSmmControl2,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_NOTIFY,

+                  SmmControlVirtualAddressChangeEvent,

+                  NULL,

+                  &gEfiEventVirtualAddressChangeGuid,

+                  &Event

+                  );

+  return Status;

+}

diff --git a/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.inf 
b/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.inf
new file mode 100644
index 0000000000..f0c2a4586b
--- /dev/null
+++ b/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.inf
@@ -0,0 +1,50 @@
+## @file

+# SMM Control runtime DXE Module

+#

+# Provides the ability to generate a software SMI.

+#

+#  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+#

+#  SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = SmmControlRuntimeDxe

+  FILE_GUID                      = C3099578-F815-4a96-84A3-FC593760181D

+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = SmmControlEntryPoint

+

+#

+# The following information is for reference only and not required by the 
build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64

+#

+

+[Sources]

+  SmmControlRuntimeDxe.c

+

+[Packages]

+  MdePkg/MdePkg.dec

+  UefiPayloadPkg/UefiPayloadPkg.dec

+

+[LibraryClasses]

+  UefiDriverEntryPoint

+  DebugLib

+  UefiBootServicesTableLib

+  UefiRuntimeLib

+  PcdLib

+  IoLib

+  HobLib

+

+[Guids]

+  gSmmRegisterInfoGuid

+  gEfiEventVirtualAddressChangeGuid

+

+[Protocols]

+  gEfiSmmControl2ProtocolGuid             ## PRODUCES

+

+[Depex]

+  TRUE

diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec 
b/UefiPayloadPkg/UefiPayloadPkg.dec
index 8f0a7e3f95..1705f28ec4 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dec
+++ b/UefiPayloadPkg/UefiPayloadPkg.dec
@@ -37,6 +37,8 @@
   gUefiSerialPortInfoGuid  = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 
0x8d, 0x62, 0xde, 0x87, 0xf1 } }

   gLoaderMemoryMapInfoGuid = { 0xa1ff7424, 0x7a1a, 0x478e, { 0xa9, 0xe4, 0x92, 
0xf3, 0x57, 0xd1, 0x28, 0x32 } }

 

+  gSmmRegisterInfoGuid     = { 0xaa9bd7a7, 0xcafb, 0x4499, { 0xa4, 0xa9, 0xb, 
0x34, 0x6b, 0x40, 0xa6, 0x22 } }

+

 [Ppis]

   gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 
0x26, 0xf1, 0x61, 0x73, 0x89} }

 

-- 
2.32.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#81122): https://edk2.groups.io/g/devel/message/81122
Mute This Topic: https://groups.io/mt/85870024/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to