mirror of https://github.com/acidanthera/audk.git
UefiPayloadPkg: Add a common SMM control Runtime DXE module
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>
This commit is contained in:
parent
87a34ca0cf
commit
e7e8ea27d4
|
@ -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
|
|
@ -0,0 +1,256 @@
|
||||||
|
/** @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Invokes SMI activation from either the preboot or runtime environment.
|
||||||
|
|
||||||
|
This function generates an SMI.
|
||||||
|
|
||||||
|
@param[in] This The EFI_SMM_CONTROL2_PROTOCOL instance.
|
||||||
|
@param[in,out] CommandPort The value written to the command port.
|
||||||
|
@param[in,out] DataPort The value written to the data port.
|
||||||
|
@param[in] Periodic Optional mechanism to engender a periodic stream.
|
||||||
|
@param[in] ActivationInterval Optional parameter to repeat at this period one
|
||||||
|
time or, if the Periodic Boolean is set, periodically.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SMI has been engendered.
|
||||||
|
@retval EFI_DEVICE_ERROR The timing is unsupported.
|
||||||
|
@retval EFI_INVALID_PARAMETER The activation period is unsupported.
|
||||||
|
@retval EFI_INVALID_PARAMETER The last periodic activation has not been cleared.
|
||||||
|
@retval EFI_NOT_STARTED The MM base service has not been initialized.
|
||||||
|
**/
|
||||||
|
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_CONTROL2_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;
|
||||||
|
}
|
|
@ -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
|
|
@ -37,6 +37,8 @@
|
||||||
gUefiSerialPortInfoGuid = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1 } }
|
gUefiSerialPortInfoGuid = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1 } }
|
||||||
gLoaderMemoryMapInfoGuid = { 0xa1ff7424, 0x7a1a, 0x478e, { 0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32 } }
|
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]
|
[Ppis]
|
||||||
gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} }
|
gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue