/** @file
File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PchSmmHelpers.h"
#include
//
// There is only one instance for SwCommBuffer.
// It's safe in SMM since there is no re-entry for the function.
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SW_CONTEXT mPchSwCommBuffer;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC SW_SOURCE_DESC = {
PCH_SMM_NO_FLAGS,
{
{
{
ACPI_ADDR_TYPE,
{R_PCH_SMI_EN}
},
S_PCH_SMI_EN,
N_PCH_SMI_EN_APMC
},
NULL_BIT_DESC_INITIALIZER
},
{
{
{
ACPI_ADDR_TYPE,
{R_PCH_SMI_STS}
},
S_PCH_SMI_STS,
N_PCH_SMI_STS_APM
}
},
{
{
ACPI_ADDR_TYPE,
{R_PCH_SMI_STS}
},
S_PCH_SMI_STS,
N_PCH_SMI_STS_APM
}
};
/**
Get the Software Smi value
@param[in] Record No use
@param[out] Context The context that includes Software Smi value to be filled
**/
VOID
EFIAPI
SwGetContext (
IN DATABASE_RECORD *Record,
OUT PCH_SMM_CONTEXT *Context
)
{
UINT8 ApmCnt;
ApmCnt = IoRead8 ((UINTN) R_PCH_APM_CNT);
Context->Sw.SwSmiInputValue = ApmCnt;
}
/**
Check whether software SMI value of two contexts match
@param[in] Context1 Context 1 that includes software SMI value 1
@param[in] Context2 Context 2 that includes software SMI value 2
@retval FALSE Software SMI value match
@retval TRUE Software SMI value don't match
**/
BOOLEAN
EFIAPI
SwCmpContext (
IN PCH_SMM_CONTEXT *Context1,
IN PCH_SMM_CONTEXT *Context2
)
{
return (BOOLEAN) (Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue);
}
/**
Gather the CommBuffer information of SmmSwDispatch2.
@param[in] Record No use
@param[out] CommBuffer Point to the CommBuffer structure
@param[out] CommBufferSize Point to the Size of CommBuffer structure
**/
VOID
EFIAPI
SwGetCommBuffer (
IN DATABASE_RECORD *Record,
OUT VOID **CommBuffer,
OUT UINTN *CommBufferSize
)
{
EFI_STATUS Status;
EFI_SMM_SAVE_STATE_IO_INFO SmiIoInfo;
UINTN Index;
ASSERT (Record->ProtocolType == SwType);
mPchSwCommBuffer.CommandPort = IoRead8 (R_PCH_APM_CNT);
mPchSwCommBuffer.DataPort = IoRead8 (R_PCH_APM_STS);
//
// Try to find which CPU trigger SWSMI
//
mPchSwCommBuffer.SwSmiCpuIndex = 0;
for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
Status = mSmmCpuProtocol->ReadSaveState (
mSmmCpuProtocol,
sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
EFI_SMM_SAVE_STATE_REGISTER_IO,
Index,
&SmiIoInfo
);
if (EFI_ERROR (Status)) {
continue;
}
if (SmiIoInfo.IoPort == R_PCH_APM_CNT) {
//
// Find matched CPU.
//
mPchSwCommBuffer.SwSmiCpuIndex = Index;
break;
}
}
///
/// Return the CommBuffer
///
*CommBuffer = (VOID *) &mPchSwCommBuffer;
*CommBufferSize = sizeof (EFI_SMM_SW_CONTEXT);
}
/**
Init required protocol for Pch Sw Dispatch protocol.
**/
VOID
PchSwDispatchInit (
VOID
)
{
EFI_STATUS Status;
//
// Locate PI SMM CPU protocol
//
Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
ASSERT_EFI_ERROR (Status);
}