/** @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); }