2439 lines
74 KiB
C
2439 lines
74 KiB
C
/** @file
|
|
|
|
;******************************************************************************
|
|
;* Copyright 2021 Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corp.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
/** @file
|
|
This function handle the register/unregister of PCH specific SMI events.
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2014 - 2021 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains an 'Intel Peripheral Driver' and is uniquely identified as
|
|
"Intel Reference Module" and is licensed for Intel CPUs and chipsets under
|
|
the terms of your license agreement with Intel or your vendor. This file may
|
|
be modified by the user, subject to additional terms of the license agreement.
|
|
|
|
@par Specification Reference:
|
|
**/
|
|
#include "PchSmmHelpers.h"
|
|
#include <Library/SmiHandlerProfileLib.h>
|
|
#include <Register/PchRegs.h>
|
|
#include <Register/PchPcrRegs.h>
|
|
#include <Register/PmcRegs.h>
|
|
#include <Register/TcoRegs.h>
|
|
#include <Register/PchRegsLpc.h>
|
|
#include <Register/SpiRegs.h>
|
|
#include <Register/PchRegsPsth.h>
|
|
#include <Library/PchPciBdfLib.h>
|
|
#include <Library/S3BootScriptLib.h>
|
|
#include "PchSmiHelper.h"
|
|
|
|
extern PCH_SMM_SOURCE_DESC PchPcieSmiRpHotPlugTemplate;
|
|
extern PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkActiveTemplate;
|
|
extern PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkEqTemplate;
|
|
|
|
/**
|
|
The internal function used to create and insert a database record
|
|
for SMI record of Pch Smi types.
|
|
|
|
@param[in] SrcDesc The pointer to the SMI source description
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[in] PchSmiType Specific SMI type of PCH SMI
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
**/
|
|
EFI_STATUS
|
|
PchSmiRecordInsert (
|
|
IN CONST PCH_SMM_SOURCE_DESC *SrcDesc,
|
|
IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
|
|
IN PCH_SMI_TYPES PchSmiType,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD Record;
|
|
|
|
if (SrcDesc == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
ZeroMem (&Record, sizeof (DATABASE_RECORD));
|
|
//
|
|
// Gather information about the registration request
|
|
//
|
|
Record.Signature = DATABASE_RECORD_SIGNATURE;
|
|
Record.PchSmiCallback = DispatchFunction;
|
|
Record.ProtocolType = PchSmiDispatchType;
|
|
Record.PchSmiType = PchSmiType;
|
|
|
|
CopyMem (&Record.SrcDesc, SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
|
|
Status = SmmCoreInsertRecord (
|
|
&Record,
|
|
DispatchHandle
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// TCO_STS bit that needs to be cleared
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mDescSrcTcoSts = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
NULL_BIT_DESC_INITIALIZER,
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
};
|
|
|
|
/**
|
|
Clear the TCO SMI status bit and block after the SMI handling is done
|
|
|
|
@param[in] SrcDesc Pointer to the PCH SMI source description table
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PchTcoSmiClearSourceAndBlock (
|
|
CONST PCH_SMM_SOURCE_DESC *SrcDesc
|
|
)
|
|
{
|
|
PchSmmClearSourceAndBlock (SrcDesc);
|
|
//
|
|
// Any TCO-based status bits require special handling.
|
|
// SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
|
|
//
|
|
PchSmmClearSource (&mDescSrcTcoSts);
|
|
}
|
|
|
|
/**
|
|
Clear the TCO SMI status bit after the SMI handling is done
|
|
|
|
@param[in] SrcDesc Pointer to the PCH SMI source description table
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PchTcoSmiClearSource (
|
|
CONST PCH_SMM_SOURCE_DESC *SrcDesc
|
|
)
|
|
{
|
|
PchSmmClearSource (SrcDesc);
|
|
//
|
|
// Any TCO-based status bits require special handling.
|
|
// SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
|
|
//
|
|
PchSmmClearSource (&mDescSrcTcoSts);
|
|
}
|
|
|
|
/**
|
|
Initialize Source descriptor structure
|
|
|
|
@param[in] SrcDesc Pointer to the PCH SMI source description table
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
NullInitSourceDesc (
|
|
PCH_SMM_SOURCE_DESC *SrcDesc
|
|
)
|
|
{
|
|
ZeroMem (SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
|
|
SrcDesc->En[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
|
|
SrcDesc->En[1].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
|
|
SrcDesc->Sts[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
|
|
SrcDesc->PmcSmiSts.Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
|
|
}
|
|
|
|
//
|
|
// Mch srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMch = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_TCO
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO1_STS}
|
|
},
|
|
S_TCO_IO_TCO1_STS,
|
|
N_TCO_IO_TCO1_STS_DMISMI
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of MCH event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiMchRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescMch,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiMchType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSmiClearSource;
|
|
PchSmmClearSource (&Record->SrcDesc);
|
|
PchSmmEnableSource (&Record->SrcDesc);
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// TcoTimeout srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_TCO
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO1_STS}
|
|
},
|
|
S_TCO_IO_TCO1_STS,
|
|
N_TCO_IO_TCO1_STS_TIMEOUT
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of TcoTimeout event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiTcoTimeoutRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescTcoTimeout,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiTcoTimeoutType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSmiClearSource;
|
|
PchSmmClearSource (&Record->SrcDesc);
|
|
PchSmmEnableSource (&Record->SrcDesc);
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// OsTco srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescOsTco = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_TCO
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO1_STS}
|
|
},
|
|
S_TCO_IO_TCO1_STS,
|
|
N_TCO_IO_TCO1_STS_SW_TCO_SMI
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of OS TCO event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiOsTcoRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescOsTco,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiOsTcoType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSmiClearSource;
|
|
PchSmmClearSource (&Record->SrcDesc);
|
|
PchSmmEnableSource (&Record->SrcDesc);
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Nmi
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNmi = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO1_CNT}
|
|
},
|
|
S_TCO_IO_TCO1_CNT,
|
|
N_TCO_IO_TCO1_CNT_NMI2SMI_EN
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO1_STS}
|
|
},
|
|
S_TCO_IO_TCO1_STS,
|
|
N_TCO_IO_TCO1_STS_NMI2SMI
|
|
}
|
|
},
|
|
//
|
|
// NOTE: The status of NMI2SMI won't reflect to PMC SMI_STS.
|
|
// So skip the top level status check and check the TCO1_STS directly.
|
|
//
|
|
NULL_BIT_DESC_INITIALIZER
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of NMI event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiNmiRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescNmi,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiNmiType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSmiClearSource;
|
|
PchSmmClearSource (&Record->SrcDesc);
|
|
PchSmmEnableSource (&Record->SrcDesc);
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// IntruderDetect srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_TCO
|
|
},
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO2_CNT}
|
|
},
|
|
S_TCO_IO_TCO2_CNT,
|
|
N_TCO_IO_TCO2_CNT_INTRD_SEL
|
|
}
|
|
},
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO2_STS}
|
|
},
|
|
S_TCO_IO_TCO2_STS,
|
|
N_TCO_IO_TCO2_STS_INTRD_DET
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of Intruder Detect event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiIntruderDetRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescIntruderDet,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiIntruderDetectType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSmiClearSourceAndBlock;
|
|
PchSmmClearSource (&Record->SrcDesc);
|
|
PchSmmEnableSource (&Record->SrcDesc);
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// SpiBiosWp srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_TCO
|
|
},
|
|
{
|
|
{
|
|
PCIE_ADDR_TYPE,
|
|
{ 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
|
|
},
|
|
S_SPI_CFG_BC,
|
|
N_SPI_CFG_BC_BLE
|
|
},
|
|
},
|
|
{
|
|
{
|
|
{
|
|
PCIE_ADDR_TYPE,
|
|
{ 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
|
|
},
|
|
S_SPI_CFG_BC,
|
|
N_SPI_CFG_BC_SYNC_SS
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
};
|
|
|
|
/**
|
|
Special handling for SPI Write Protect
|
|
|
|
@param[in] SrcDesc Not used
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PchTcoSpiWpClearSource (
|
|
CONST PCH_SMM_SOURCE_DESC *SrcDesc
|
|
)
|
|
{
|
|
UINT64 SpiRegBase;
|
|
UINT32 BiosControl;
|
|
UINT32 Timeout;
|
|
|
|
SpiRegBase = SpiPciCfgBase ();
|
|
PciSegmentAndThenOr32 (
|
|
SpiRegBase + R_SPI_CFG_BC,
|
|
(UINT32) ~B_SPI_CFG_BC_ASYNC_SS,
|
|
B_SPI_CFG_BC_SYNC_SS
|
|
);
|
|
//
|
|
// Ensure the SYNC is cleared
|
|
//
|
|
Timeout = 1000;
|
|
do {
|
|
BiosControl = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BC);
|
|
Timeout--;
|
|
} while ((BiosControl & B_SPI_CFG_BC_SYNC_SS) && (Timeout > 0));
|
|
|
|
//
|
|
// Any TCO-based status bits require special handling.
|
|
// SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
|
|
//
|
|
PchSmmClearSource (&mDescSrcTcoSts);
|
|
}
|
|
|
|
/**
|
|
Set SMI_EN_TCO to enable TCO SMI.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
PchSetSmiEnTco (
|
|
VOID
|
|
)
|
|
{
|
|
//[-start-211108-IB18410124-add]//
|
|
UINT32 Data32And;
|
|
UINT32 Data32Or;
|
|
//[-end-211108-IB18410124-add]//
|
|
|
|
IoOr32 (mAcpiBaseAddr + R_ACPI_IO_SMI_EN, B_ACPI_IO_SMI_EN_TCO);
|
|
|
|
//[-start-211108-IB18410124-add]//
|
|
Data32And = 0xFFFFFFFF;
|
|
Data32Or |= B_ACPI_IO_SMI_EN_TCO;
|
|
S3BootScriptSaveIoReadWrite (
|
|
S3BootScriptWidthUint32,
|
|
(UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN),
|
|
&Data32Or, // Data to be ORed
|
|
&Data32And // Data to be ANDed
|
|
);
|
|
//[-end-211108-IB18410124-add]//
|
|
}
|
|
|
|
/**
|
|
The register function used to register SMI handler of BIOS write protect event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiSpiBiosWpRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescSpiBiosWp,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiSpiBiosWpType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSpiWpClearSource;
|
|
PchTcoSpiWpClearSource (NULL);
|
|
//
|
|
// It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
|
|
// Only enable SMI_EN_TCO.
|
|
//
|
|
PchSetSmiEnTco ();
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// LpcBiosWp srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_TCO
|
|
},
|
|
{
|
|
{
|
|
PCIE_ADDR_TYPE,
|
|
{ 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
|
|
},
|
|
S_LPC_CFG_BC,
|
|
N_LPC_CFG_BC_LE
|
|
}
|
|
},
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO1_STS}
|
|
},
|
|
S_TCO_IO_TCO1_STS,
|
|
N_TCO_IO_TCO1_STS_BIOSWR
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of LPC BIOS write protect event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiLpcBiosWpRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
if (IsEspiEnabled ()) {
|
|
//
|
|
// Status is D31F0's PCBC.BWPDS
|
|
//
|
|
ASSERT (FALSE);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescLpcBiosWp,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiLpcBiosWpType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSmiClearSource;
|
|
PchSmmClearSource (&Record->SrcDesc);
|
|
//
|
|
// It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
|
|
// Only enable SMI_EN_TCO.
|
|
//
|
|
PchSetSmiEnTco ();
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// NEWCENTURY_STS bit that needs to be cleared
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNewCentury = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_TCO
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
TCO_ADDR_TYPE,
|
|
{R_TCO_IO_TCO1_STS}
|
|
},
|
|
S_TCO_IO_TCO1_STS,
|
|
N_TCO_IO_TCO1_STS_NEWCENTURY
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_TCO
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of NEW CENTURY event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiNewCenturyRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescNewCentury,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchTcoSmiNewCenturyType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchTcoSmiClearSourceAndBlock;
|
|
PchSmmClearSource (&Record->SrcDesc);
|
|
PchSmmEnableSource (&Record->SrcDesc);
|
|
SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Unregister a child SMI source dispatch function with a parent SMM driver
|
|
|
|
@param[in] This Protocol instance pointer.
|
|
@param[in] DispatchHandle Handle of dispatch function to deregister.
|
|
|
|
@retval EFI_SUCCESS The dispatch function has been successfully
|
|
unregistered and the SMI source has been disabled
|
|
if there are no other registered child dispatch
|
|
functions for this SMI source.
|
|
@retval EFI_INVALID_PARAMETER Handle is invalid.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchTcoSmiUnRegister (
|
|
IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
|
|
IN EFI_HANDLE DispatchHandle
|
|
)
|
|
{
|
|
DATABASE_RECORD *Record;
|
|
EFI_STATUS Status;
|
|
|
|
Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
|
|
if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
|
|
(Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
|
|
(Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
|
|
(Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
|
|
(Record->SrcDesc.En[1].Bit == N_SPI_CFG_BC_BLE)) {
|
|
//
|
|
// SPI Write Protect cannot be disabled
|
|
//
|
|
return EFI_ACCESS_DENIED;
|
|
} else if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
|
|
(Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == LpcDevNumber ()) &&
|
|
(Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == LpcFuncNumber ()) &&
|
|
(Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_LPC_CFG_BC) &&
|
|
(Record->SrcDesc.En[1].Bit == N_LPC_CFG_BC_LE)) {
|
|
//
|
|
// eSPI/LPC Write Protect cannot be disabled
|
|
//
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileUnregisterHandler (&gPchTcoSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
The register function used to register SMI handler of PCIE RP hotplug event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchPcieSmiHotPlugRegister (
|
|
IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
|
|
IN UINTN RpIndex,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN RpDev;
|
|
UINTN RpFun;
|
|
PCH_SMM_PCIE_REGISTER_CONTEXT Context;
|
|
DATABASE_RECORD *Record;
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
// PCIe RP Hot Plug SMM source descriptor defined as NULL- SMI handling not supported
|
|
if (IS_BIT_DESC_NULL (PchPcieSmiRpHotPlugTemplate.PmcSmiSts) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpHotPlugTemplate.En[0]) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpHotPlugTemplate.En[1]) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpHotPlugTemplate.Sts[0])) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
|
|
|
|
//
|
|
// Patch the RP device number and function number of srcdesc.
|
|
//
|
|
PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
|
|
PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
|
|
PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
|
|
PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&PchPcieSmiRpHotPlugTemplate,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchPcieSmiRpHotplugType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpHotplugType;
|
|
Record->ChildContext.Pcie.RpIndex = RpIndex;
|
|
Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
|
|
SmiHandlerProfileRegisterHandler (
|
|
&gPchPcieSmiDispatchProtocolGuid,
|
|
(EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction,
|
|
(UINTN)RETURN_ADDRESS (0),
|
|
&Context,
|
|
sizeof (Context)
|
|
);
|
|
}
|
|
PchSmmClearSource (&PchPcieSmiRpHotPlugTemplate);
|
|
PchSmmEnableSource (&PchPcieSmiRpHotPlugTemplate);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
The register function used to register SMI handler of PCIE RP link active event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchPcieSmiLinkActiveRegister (
|
|
IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
|
|
IN UINTN RpIndex,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN RpDev;
|
|
UINTN RpFun;
|
|
PCH_SMM_PCIE_REGISTER_CONTEXT Context;
|
|
DATABASE_RECORD *Record;
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
// PCIe RP Link Active SMM source descriptor defined as NULL- SMI handling not supported
|
|
if (IS_BIT_DESC_NULL (PchPcieSmiRpLinkActiveTemplate.PmcSmiSts) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpLinkActiveTemplate.En[0]) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpLinkActiveTemplate.En[1]) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpLinkActiveTemplate.Sts[0])) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
|
|
|
|
//
|
|
// Patch the RP device number and function number of srcdesc.
|
|
//
|
|
PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
|
|
PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
|
|
PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
|
|
PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&PchPcieSmiRpLinkActiveTemplate,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchPcieSmiRpLinkActiveType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpLinkActiveType;
|
|
Record->ChildContext.Pcie.RpIndex = RpIndex;
|
|
Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
|
|
SmiHandlerProfileRegisterHandler (
|
|
&gPchPcieSmiDispatchProtocolGuid,
|
|
(EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction,
|
|
(UINTN)RETURN_ADDRESS (0),
|
|
&Context,
|
|
sizeof (Context)
|
|
);
|
|
}
|
|
PchSmmClearSource (&PchPcieSmiRpLinkActiveTemplate);
|
|
PchSmmEnableSource (&PchPcieSmiRpLinkActiveTemplate);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
The register function used to register SMI handler of PCIE RP Link Equalization Request event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchPcieSmiLinkEqRegister (
|
|
IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
|
|
IN UINTN RpIndex,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
UINTN RpDev;
|
|
UINTN RpFun;
|
|
EFI_STATUS Status;
|
|
PCH_SMM_PCIE_REGISTER_CONTEXT Context;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
// PCIe RP Link Equalization SMM source descriptor defined as NULL- SMI handling not supported
|
|
if (IS_BIT_DESC_NULL (PchPcieSmiRpLinkEqTemplate.PmcSmiSts) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpLinkEqTemplate.En[0]) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpLinkEqTemplate.En[1]) &&
|
|
IS_BIT_DESC_NULL (PchPcieSmiRpLinkEqTemplate.Sts[0])) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
|
|
|
|
//
|
|
// Patch the RP device number and function number of srcdesc.
|
|
//
|
|
PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
|
|
PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
|
|
PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
|
|
PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&PchPcieSmiRpLinkEqTemplate,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchPcieSmiRpLinkEqType,
|
|
DispatchHandle
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpLinkEqType;
|
|
Record->ChildContext.Pcie.RpIndex = RpIndex;
|
|
Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
|
|
SmiHandlerProfileRegisterHandler (
|
|
&gPchPcieSmiDispatchProtocolGuid,
|
|
(EFI_SMM_HANDLER_ENTRY_POINT2) DispatchFunction,
|
|
(UINTN)RETURN_ADDRESS (0),
|
|
&Context,
|
|
sizeof (Context)
|
|
);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Unregister a child SMI source dispatch function with a parent SMM driver
|
|
|
|
@param[in] This Protocol instance pointer.
|
|
@param[in] DispatchHandle Handle of dispatch function to deregister.
|
|
|
|
@retval EFI_SUCCESS The dispatch function has been successfully
|
|
unregistered and the SMI source has been disabled
|
|
if there are no other registered child dispatch
|
|
functions for this SMI source.
|
|
@retval EFI_INVALID_PARAMETER Handle is invalid.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchPcieSmiUnRegister (
|
|
IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
|
|
IN EFI_HANDLE DispatchHandle
|
|
)
|
|
{
|
|
DATABASE_RECORD *RecordToDelete;
|
|
EFI_STATUS Status;
|
|
|
|
RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
|
|
Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileUnregisterHandler (
|
|
&gPchPcieSmiDispatchProtocolGuid,
|
|
RecordToDelete->Callback,
|
|
&RecordToDelete->ChildContext,
|
|
sizeof (RecordToDelete->ContextSize)
|
|
);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Pme srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPme = {
|
|
PCH_SMM_SCI_EN_DEPENDENT,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_GPE0_EN_127_96}
|
|
},
|
|
S_ACPI_IO_GPE0_EN_127_96,
|
|
N_ACPI_IO_GPE0_EN_127_96_PME
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_GPE0_STS_127_96}
|
|
},
|
|
S_ACPI_IO_GPE0_STS_127_96,
|
|
N_ACPI_IO_GPE0_STS_127_96_PME
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_GPE0
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of PME event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchAcpiSmiPmeRegister (
|
|
IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescPme,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchAcpiSmiPmeType,
|
|
DispatchHandle
|
|
);
|
|
PchSmmClearSource (&mSrcDescPme);
|
|
PchSmmEnableSource (&mSrcDescPme);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// PmeB0 srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = {
|
|
PCH_SMM_SCI_EN_DEPENDENT,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_GPE0_EN_127_96}
|
|
},
|
|
S_ACPI_IO_GPE0_EN_127_96,
|
|
N_ACPI_IO_GPE0_EN_127_96_PME_B0
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_GPE0_STS_127_96}
|
|
},
|
|
S_ACPI_IO_GPE0_STS_127_96,
|
|
N_ACPI_IO_GPE0_STS_127_96_PME_B0
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_GPE0
|
|
}
|
|
};
|
|
/**
|
|
The register function used to register SMI handler of PME B0 event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchAcpiSmiPmeB0Register (
|
|
IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescPmeB0,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchAcpiSmiPmeB0Type,
|
|
DispatchHandle
|
|
);
|
|
PchSmmClearSource (&mSrcDescPmeB0);
|
|
PchSmmEnableSource (&mSrcDescPmeB0);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// RtcAlarm srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = {
|
|
PCH_SMM_SCI_EN_DEPENDENT,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_PM1_EN}
|
|
},
|
|
S_ACPI_IO_PM1_EN,
|
|
N_ACPI_IO_PM1_EN_RTC
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_PM1_STS}
|
|
},
|
|
S_ACPI_IO_PM1_STS,
|
|
N_ACPI_IO_PM1_STS_RTC
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_PM1_STS_REG
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of RTC alarm event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchAcpiSmiRtcAlarmRegister (
|
|
IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescRtcAlarm,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchAcpiSmiRtcAlarmType,
|
|
DispatchHandle
|
|
);
|
|
|
|
PchSmmClearSource (&mSrcDescRtcAlarm);
|
|
PchSmmEnableSource (&mSrcDescRtcAlarm);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// TmrOverflow srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = {
|
|
PCH_SMM_SCI_EN_DEPENDENT,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_PM1_EN}
|
|
},
|
|
S_ACPI_IO_PM1_EN,
|
|
N_ACPI_IO_PM1_EN_TMROF
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_PM1_STS}
|
|
},
|
|
S_ACPI_IO_PM1_STS,
|
|
N_ACPI_IO_PM1_STS_TMROF
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_PM1_STS_REG
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of Timer Overflow event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchAcpiSmiTmrOverflowRegister (
|
|
IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescTmrOverflow,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchAcpiSmiTmrOverflowType,
|
|
DispatchHandle
|
|
);
|
|
PchSmmClearSource (&mSrcDescTmrOverflow);
|
|
PchSmmEnableSource (&mSrcDescTmrOverflow);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Unregister a child SMI source dispatch function with a parent SMM driver
|
|
|
|
@param[in] This Protocol instance pointer.
|
|
@param[in] DispatchHandle Handle of dispatch function to deregister.
|
|
|
|
@retval EFI_SUCCESS The dispatch function has been successfully
|
|
unregistered and the SMI source has been disabled
|
|
if there are no other registered child dispatch
|
|
functions for this SMI source.
|
|
@retval EFI_INVALID_PARAMETER Handle is invalid.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchAcpiSmiUnRegister (
|
|
IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
|
|
IN EFI_HANDLE DispatchHandle
|
|
)
|
|
{
|
|
DATABASE_RECORD *RecordToDelete;
|
|
EFI_STATUS Status;
|
|
|
|
RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
|
|
Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileUnregisterHandler (&gPchAcpiSmiDispatchProtocolGuid, RecordToDelete->Callback, NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// SerialIrq srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
NULL_BIT_DESC_INITIALIZER,
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_SERIRQ
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_SERIRQ
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of Serial IRQ event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchSmiSerialIrqRegister (
|
|
IN PCH_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescSerialIrq,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchSmiSerialIrqType,
|
|
DispatchHandle
|
|
);
|
|
PchSmmClearSource (&mSrcDescSerialIrq);
|
|
PchSmmEnableSource (&mSrcDescSerialIrq);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// McSmi srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMcSmi = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_EN}
|
|
},
|
|
S_ACPI_IO_SMI_EN,
|
|
N_ACPI_IO_SMI_EN_MCSMI
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_MCSMI
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_MCSMI
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of MCSMI event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchSmiMcSmiRegister (
|
|
IN PCH_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescMcSmi,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchSmiMcSmiType,
|
|
DispatchHandle
|
|
);
|
|
PchSmmClearSource (&mSrcDescMcSmi);
|
|
PchSmmEnableSource (&mSrcDescMcSmi);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// SmBus srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSmbus = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
NULL_BIT_DESC_INITIALIZER,
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_SMBUS
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_SMBUS
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of SMBUS event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchSmiSmbusRegister (
|
|
IN PCH_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescSmbus,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchSmiSmBusType,
|
|
DispatchHandle
|
|
);
|
|
PchSmmClearSource (&mSrcDescSmbus);
|
|
PchSmmEnableSource (&mSrcDescSmbus);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// SpiAsyncSmi srcdesc
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = {
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
PCIE_ADDR_TYPE,
|
|
{ 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
|
|
},
|
|
S_SPI_CFG_BC,
|
|
N_SPI_CFG_BC_ASE_BWP
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
PCIE_ADDR_TYPE,
|
|
{ 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
|
|
},
|
|
S_SPI_CFG_BC,
|
|
N_SPI_CFG_BC_ASYNC_SS
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_SPI
|
|
}
|
|
};
|
|
|
|
/**
|
|
Special handling for SPI Asynchronous SMI.
|
|
If SPI ASYNC SMI is enabled, De-assert SMI is sent when Flash Cycle Done
|
|
transitions from 1 to 0 or when the SMI enable becomes false.
|
|
|
|
@param[in] SrcDesc Not used
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PchSmiSpiAsyncClearSource (
|
|
CONST PCH_SMM_SOURCE_DESC *SrcDesc
|
|
)
|
|
{
|
|
UINT64 SpiRegBase;
|
|
UINT32 SpiBar0;
|
|
|
|
SpiRegBase = SpiPciCfgBase ();
|
|
SpiBar0 = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
|
|
if (SpiBar0 != PCH_SPI_BASE_ADDRESS) {
|
|
//
|
|
// Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
|
|
//
|
|
SpiBar0 = PCH_SPI_BASE_ADDRESS;
|
|
PciSegmentAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
|
|
PciSegmentWrite32 (SpiRegBase + R_SPI_CFG_BAR0, SpiBar0);
|
|
PciSegmentOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
|
|
}
|
|
|
|
MmioOr32 (SpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FDONE);
|
|
}
|
|
|
|
/**
|
|
Special handling to enable SPI Asynchronous SMI
|
|
**/
|
|
VOID
|
|
PchSmiSpiAsyncEnableSource (
|
|
VOID
|
|
)
|
|
{
|
|
UINT64 SpiRegBase;
|
|
UINT32 Data32And;
|
|
UINT32 Data32Or;
|
|
|
|
SpiRegBase = SpiPciCfgBase ();
|
|
Data32And = (UINT32) ~B_SPI_CFG_BC_SYNC_SS;
|
|
Data32Or = B_SPI_CFG_BC_ASE_BWP;
|
|
|
|
PciSegmentAndThenOr32 (
|
|
SpiRegBase + R_SPI_CFG_BC,
|
|
Data32And,
|
|
Data32Or
|
|
);
|
|
S3BootScriptSavePciCfgReadWrite (
|
|
S3BootScriptWidthUint32,
|
|
SpiRegBase + R_SPI_CFG_BC,
|
|
(VOID*) &Data32Or,
|
|
(VOID*) &Data32And
|
|
);
|
|
|
|
//
|
|
// Clear the source
|
|
//
|
|
PchSmiSpiAsyncClearSource (NULL);
|
|
}
|
|
|
|
/**
|
|
The register function used to register SMI handler of SPI Asynchronous event.
|
|
|
|
@param[in] This The pointer to the protocol itself
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchSmiSpiAsyncRegister (
|
|
IN PCH_SMI_DISPATCH_PROTOCOL *This,
|
|
IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DATABASE_RECORD *Record;
|
|
|
|
//
|
|
// Return access denied if the SmmReadyToLock event has been triggered
|
|
//
|
|
if (mReadyToLock == TRUE) {
|
|
DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescSpiAsyncSmi,
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchSmiSpiAsyncType,
|
|
DispatchHandle
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
|
|
Record->ClearSource = PchSmiSpiAsyncClearSource;
|
|
PchSmiSpiAsyncClearSource (NULL);
|
|
PchSmiSpiAsyncEnableSource ();
|
|
SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Unregister a child SMI source dispatch function with a parent SMM driver
|
|
|
|
@param[in] This Protocol instance pointer.
|
|
@param[in] DispatchHandle Handle of dispatch function to deregister.
|
|
|
|
@retval EFI_SUCCESS The dispatch function has been successfully
|
|
unregistered and the SMI source has been disabled
|
|
if there are no other registered child dispatch
|
|
functions for this SMI source.
|
|
@retval EFI_INVALID_PARAMETER Handle is invalid.
|
|
@retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
|
|
@retval EFI_ACCESS_DENIED Return access denied since SPI aync SMI handler is not able to disabled.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchSmiUnRegister (
|
|
IN PCH_SMI_DISPATCH_PROTOCOL *This,
|
|
IN EFI_HANDLE DispatchHandle
|
|
)
|
|
{
|
|
DATABASE_RECORD *Record;
|
|
UINT64 SpiRegBase;
|
|
EFI_STATUS Status;
|
|
|
|
Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
|
|
if ((Record->SrcDesc.En[0].Reg.Type == PCIE_ADDR_TYPE) &&
|
|
(Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
|
|
(Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
|
|
(Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
|
|
(Record->SrcDesc.En[0].Bit == N_SPI_CFG_BC_ASE_BWP)) {
|
|
SpiRegBase = SpiPciCfgBase ();
|
|
if (PciSegmentRead8 (SpiRegBase + R_SPI_CFG_BC) & B_SPI_CFG_BC_BILD) {
|
|
//
|
|
// SPI Asynchronous SMI cannot be disabled
|
|
//
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
}
|
|
Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
|
|
if (!EFI_ERROR (Status)) {
|
|
SmiHandlerProfileUnregisterHandler (&gPchSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Declaration of PCH TCO SMI DISPATCH PROTOCOL instance
|
|
**/
|
|
PCH_TCO_SMI_DISPATCH_PROTOCOL mPchTcoSmiDispatchProtocol = {
|
|
PCH_TCO_SMI_DISPATCH_REVISION, // Revision
|
|
PchTcoSmiUnRegister, // Unregister
|
|
PchTcoSmiMchRegister, // Mch
|
|
PchTcoSmiTcoTimeoutRegister, // TcoTimeout
|
|
PchTcoSmiOsTcoRegister, // OsTco
|
|
PchTcoSmiNmiRegister, // Nmi
|
|
PchTcoSmiIntruderDetRegister, // IntruderDectect
|
|
PchTcoSmiSpiBiosWpRegister, // SpiBiosWp
|
|
PchTcoSmiLpcBiosWpRegister, // LpcBiosWp
|
|
PchTcoSmiNewCenturyRegister // NewCentury
|
|
};
|
|
|
|
/**
|
|
Declaration of PCH PCIE SMI DISPATCH PROTOCOL instance
|
|
**/
|
|
PCH_PCIE_SMI_DISPATCH_PROTOCOL mPchPcieSmiDispatchProtocol = {
|
|
PCH_PCIE_SMI_DISPATCH_REVISION, // Revision
|
|
PchPcieSmiUnRegister, // Unregister
|
|
PchPcieSmiHotPlugRegister, // PcieRpXHotPlug
|
|
PchPcieSmiLinkActiveRegister, // PcieRpXLinkActive
|
|
PchPcieSmiLinkEqRegister // PcieRpXLinkEq
|
|
};
|
|
|
|
/**
|
|
Declaration of PCH ACPI SMI DISPATCH PROTOCOL instance
|
|
**/
|
|
PCH_ACPI_SMI_DISPATCH_PROTOCOL mPchAcpiSmiDispatchProtocol = {
|
|
PCH_ACPI_SMI_DISPATCH_REVISION, // Revision
|
|
PchAcpiSmiUnRegister, // Unregister
|
|
PchAcpiSmiPmeRegister, // Pme
|
|
PchAcpiSmiPmeB0Register, // PmeB0
|
|
PchAcpiSmiRtcAlarmRegister, // RtcAlarm
|
|
PchAcpiSmiTmrOverflowRegister // TmrOverflow
|
|
};
|
|
|
|
/**
|
|
Declaration of MISC PCH SMI DISPATCH PROTOCOL instance
|
|
**/
|
|
PCH_SMI_DISPATCH_PROTOCOL mPchSmiDispatchProtocol = {
|
|
PCH_SMI_DISPATCH_REVISION, // Revision
|
|
PchSmiUnRegister, // Unregister
|
|
PchSmiSerialIrqRegister, // SerialIrq
|
|
PchSmiMcSmiRegister, // McSmi
|
|
PchSmiSmbusRegister, // SmBus
|
|
PchSmiSpiAsyncRegister // SpiAsync
|
|
};
|
|
|
|
/**
|
|
Install protocols of PCH specifics SMI types, including
|
|
PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
|
|
|
|
@retval the result of protocol installation
|
|
**/
|
|
EFI_STATUS
|
|
InstallPchSmiDispatchProtocols (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_HANDLE Handle;
|
|
EFI_STATUS Status;
|
|
|
|
Handle = NULL;
|
|
Status = gSmst->SmmInstallProtocolInterface (
|
|
&Handle,
|
|
&gPchTcoSmiDispatchProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&mPchTcoSmiDispatchProtocol
|
|
);
|
|
if (!IsPchServer ()) {
|
|
// Do not install BIOS SMI handlers for server's PCIe Root Ports
|
|
// PCIe features like Hot Plug are handled by PCI Express Native Control feature in operating systems
|
|
Status = gSmst->SmmInstallProtocolInterface (
|
|
&Handle,
|
|
&gPchPcieSmiDispatchProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&mPchPcieSmiDispatchProtocol
|
|
);
|
|
}
|
|
Status = gSmst->SmmInstallProtocolInterface (
|
|
&Handle,
|
|
&gPchAcpiSmiDispatchProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&mPchAcpiSmiDispatchProtocol
|
|
);
|
|
Status = gSmst->SmmInstallProtocolInterface (
|
|
&Handle,
|
|
&gPchSmiDispatchProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&mPchSmiDispatchProtocol
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
The function to dispatch all callback function of PCH SMI types.
|
|
|
|
@retval EFI_SUCCESS Function successfully completed
|
|
@retval EFI_UNSUPPORTED no
|
|
**/
|
|
EFI_STATUS
|
|
PchSmiTypeCallbackDispatcher (
|
|
IN DATABASE_RECORD *Record
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PCH_SMI_TYPES PchSmiType;
|
|
UINTN RpIndex;
|
|
PCH_PCIE_SMI_RP_CONTEXT RpContext;
|
|
|
|
PchSmiType = Record->PchSmiType;
|
|
Status = EFI_SUCCESS;
|
|
|
|
switch (PchSmiType) {
|
|
case PchTcoSmiMchType:
|
|
case PchTcoSmiTcoTimeoutType:
|
|
case PchTcoSmiOsTcoType:
|
|
case PchTcoSmiNmiType:
|
|
case PchTcoSmiIntruderDetectType:
|
|
case PchTcoSmiSpiBiosWpType:
|
|
case PchTcoSmiLpcBiosWpType:
|
|
case PchTcoSmiNewCenturyType:
|
|
((PCH_TCO_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
|
|
break;
|
|
case PchPcieSmiRpHotplugType:
|
|
case PchPcieSmiRpLinkActiveType:
|
|
case PchPcieSmiRpLinkEqType:
|
|
RpContext.BusNum = DEFAULT_PCI_BUS_NUMBER_PCH;
|
|
RpContext.DevNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev;
|
|
RpContext.FuncNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc;
|
|
GetPcieRpNumber (RpContext.DevNum, RpContext.FuncNum, &RpIndex);
|
|
RpContext.RpIndex = (UINT8) RpIndex;
|
|
((PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link, &RpContext);
|
|
break;
|
|
case PchAcpiSmiPmeType:
|
|
case PchAcpiSmiPmeB0Type:
|
|
case PchAcpiSmiRtcAlarmType:
|
|
case PchAcpiSmiTmrOverflowType:
|
|
((PCH_ACPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
|
|
break;
|
|
case PchEspiSmiEspiSlaveType:
|
|
((PCH_ESPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
|
|
break;
|
|
case PchSmiSerialIrqType:
|
|
case PchSmiMcSmiType:
|
|
case PchSmiSmBusType:
|
|
case PchSmiSpiAsyncType:
|
|
case PchIoTrapSmiType: ///< internal type for IoTrap
|
|
((PCH_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
|
|
break;
|
|
default:
|
|
Status = EFI_UNSUPPORTED;
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIoTrap[4] = {
|
|
//
|
|
// PCH I/O Trap register 0 monitor
|
|
//
|
|
{
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG0) }
|
|
},
|
|
4,
|
|
0
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
|
|
},
|
|
1,
|
|
0
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_MONITOR
|
|
}
|
|
},
|
|
//
|
|
// PCH I/O Trap register 1 monitor
|
|
//
|
|
{
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG1) }
|
|
},
|
|
4,
|
|
0
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
|
|
},
|
|
1,
|
|
1
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_MONITOR
|
|
}
|
|
},
|
|
//
|
|
// PCH I/O Trap register 2 monitor
|
|
//
|
|
{
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG2) }
|
|
},
|
|
4,
|
|
0
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
|
|
},
|
|
1,
|
|
2
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_MONITOR
|
|
}
|
|
},
|
|
//
|
|
// PCH I/O Trap register 3 monitor,
|
|
//
|
|
{
|
|
PCH_SMM_NO_FLAGS,
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG3) }
|
|
},
|
|
4,
|
|
0
|
|
},
|
|
NULL_BIT_DESC_INITIALIZER
|
|
},
|
|
{
|
|
{
|
|
{
|
|
PCR_ADDR_TYPE,
|
|
{PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
|
|
},
|
|
1,
|
|
3
|
|
}
|
|
},
|
|
{
|
|
{
|
|
ACPI_ADDR_TYPE,
|
|
{R_ACPI_IO_SMI_STS}
|
|
},
|
|
S_ACPI_IO_SMI_STS,
|
|
N_ACPI_IO_SMI_STS_MONITOR
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
The register function used to register SMI handler of IoTrap event.
|
|
This is internal function and only used by Iotrap module.
|
|
|
|
@param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
|
|
@param[in] IoTrapIndex Index number of IOTRAP register
|
|
@param[out] DispatchHandle Handle of dispatch function to register.
|
|
|
|
@retval EFI_INVALID_PARAMETER Error with NULL SMI source description
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
|
|
@retval EFI_SUCCESS The database record is created successfully.
|
|
**/
|
|
EFI_STATUS
|
|
PchInternalIoTrapSmiRegister (
|
|
IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
|
|
IN UINTN IoTrapIndex,
|
|
OUT EFI_HANDLE *DispatchHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = PchSmiRecordInsert (
|
|
&mSrcDescIoTrap[IoTrapIndex],
|
|
(PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
|
|
PchIoTrapSmiType,
|
|
DispatchHandle
|
|
);
|
|
PchSmmClearSource (&mSrcDescIoTrap[IoTrapIndex]);
|
|
PchSmmEnableSource (&mSrcDescIoTrap[IoTrapIndex]);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Unregister a child SMI source dispatch function with a parent SMM driver
|
|
|
|
@param[in] DispatchHandle Handle of dispatch function to deregister.
|
|
|
|
@retval EFI_SUCCESS The dispatch function has been successfully
|
|
unregistered and the SMI source has been disabled
|
|
if there are no other registered child dispatch
|
|
functions for this SMI source.
|
|
@retval EFI_INVALID_PARAMETER Handle is invalid.
|
|
**/
|
|
EFI_STATUS
|
|
PchInternalIoTrapSmiUnRegister (
|
|
IN EFI_HANDLE DispatchHandle
|
|
)
|
|
{
|
|
return PchSmmCoreUnRegister (NULL, DispatchHandle);
|
|
}
|
|
|
|
/**
|
|
Performs update of SmiDispatch descriptors with values that have to be evaluated during runtime.
|
|
**/
|
|
VOID
|
|
PchSmiDispatchUpdateDescriptors (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 SpiPcieAddr;
|
|
UINT32 LpcPcieAddr;
|
|
|
|
SpiPcieAddr = ((DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
|
|
(SpiDevNumber () << 19) |
|
|
(SpiFuncNumber () << 16) |
|
|
R_SPI_CFG_BC);
|
|
LpcPcieAddr = ((DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
|
|
(LpcDevNumber () << 19) |
|
|
(LpcFuncNumber () << 16) |
|
|
R_LPC_CFG_BC);
|
|
//
|
|
// mSrcDescSpiBiosWp
|
|
//
|
|
mSrcDescSpiBiosWp.En[1].Reg.Data.raw = SpiPcieAddr;
|
|
mSrcDescSpiBiosWp.Sts[0].Reg.Data.raw = SpiPcieAddr;
|
|
|
|
//
|
|
// mSrcDescLpcBiosWp
|
|
//
|
|
mSrcDescLpcBiosWp.En[1].Reg.Data.raw = LpcPcieAddr;
|
|
|
|
//
|
|
// mSrcDescSpiAsyncSmi
|
|
//
|
|
mSrcDescSpiAsyncSmi.En[0].Reg.Data.raw = SpiPcieAddr;
|
|
mSrcDescSpiAsyncSmi.Sts[0].Reg.Data.raw = SpiPcieAddr;
|
|
} |