/** @file This function handle the register/unregister of PCH specific SMI events. Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "PchSmmHelpers.h" /** 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 EFI_GUID *ProtocolGuid, IN 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; PCH_SMM_SOURCE_DESC NullSourceDesc; // // Initialize NullSourceDesc // NullInitSourceDesc (&NullSourceDesc); if (CompareSources (SrcDesc, &NullSourceDesc)) { return EFI_INVALID_PARAMETER; } Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record); if (EFI_ERROR (Status)) { ASSERT (FALSE); return EFI_OUT_OF_RESOURCES; } SetMem (Record, sizeof (DATABASE_RECORD), 0); // // Gather information about the registration request // Record->Signature = DATABASE_RECORD_SIGNATURE; Record->PchSmiCallback = DispatchFunction; Record->ProtocolType = PchSmiDispatchType; Record->ProtocolGuid = ProtocolGuid; Record->PchSmiType = PchSmiType; Record->ContextFunctions.GetContext = NULL; Record->ContextFunctions.CmpContext = NULL; Record->ContextFunctions.GetCommBuffer = NULL; Record->ClearSource = NULL; CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (SrcDesc), sizeof (PCH_SMM_SOURCE_DESC)); // // After ensuring the source of event is not null, we will insert the record into the database // InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link); // // Child's handle will be the address linked list link in the record // *DispatchHandle = (EFI_HANDLE) (&Record->Link); if (ProtocolGuid != NULL) { SmiHandlerProfileRegisterHandler (ProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), &PchSmiType, sizeof(PchSmiType)); } return EFI_SUCCESS; } EFI_STATUS PchSmiRecordUnRegister ( IN EFI_HANDLE DispatchHandle ) { return PchSmmCoreUnRegister(NULL, DispatchHandle); } // // TCO_STS bit that needs to be cleared // PCH_SMM_SOURCE_DESC mDescSrcTcoSts = { PCH_SMM_NO_FLAGS, { NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( 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 ( 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 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 // PCH_SMM_SOURCE_DESC mSrcDescMch = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_TCO }, NULL_BIT_DESC_INITIALIZER }, { { { TCO_ADDR_TYPE, {R_PCH_TCO1_STS} }, S_PCH_TCO1_STS, N_PCH_TCO1_STS_DMISMI } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchTcoSmiDispatchProtocolGuid, &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); } return Status; } // // TcoTimeout srcdesc // PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_TCO }, NULL_BIT_DESC_INITIALIZER }, { { { TCO_ADDR_TYPE, {R_PCH_TCO1_STS} }, S_PCH_TCO1_STS, N_PCH_TCO1_STS_TIMEOUT } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchTcoSmiDispatchProtocolGuid, &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); } return Status; } // // OsTco srcdesc // PCH_SMM_SOURCE_DESC mSrcDescOsTco = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_TCO }, NULL_BIT_DESC_INITIALIZER }, { { { TCO_ADDR_TYPE, {R_PCH_TCO1_STS} }, S_PCH_TCO1_STS, N_PCH_TCO1_STS_SW_TCO_SMI } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchTcoSmiDispatchProtocolGuid, &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); } return Status; } // // Nmi // PCH_SMM_SOURCE_DESC mSrcDescNmi = { PCH_SMM_NO_FLAGS, { { { TCO_ADDR_TYPE, {R_PCH_TCO1_CNT} }, S_PCH_TCO1_CNT, N_PCH_TCO_CNT_NMI2SMI_EN }, NULL_BIT_DESC_INITIALIZER }, { { { TCO_ADDR_TYPE, {R_PCH_TCO1_STS} }, S_PCH_TCO1_STS, N_PCH_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 ( &gPchTcoSmiDispatchProtocolGuid, &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); } return Status; } // // IntruderDetect srcdesc // PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_TCO }, { { TCO_ADDR_TYPE, {R_PCH_TCO2_CNT} }, S_PCH_TCO2_CNT, N_PCH_TCO2_CNT_INTRD_SEL } }, { { { TCO_ADDR_TYPE, {R_PCH_TCO2_STS} }, S_PCH_TCO2_STS, N_PCH_TCO2_STS_INTRD_DET } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchTcoSmiDispatchProtocolGuid, &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); } return Status; } // // SpiBiosWp srcdesc // PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_TCO }, { { PCIE_ADDR_TYPE, { ( (DEFAULT_PCI_BUS_NUMBER_PCH << 24) | (PCI_DEVICE_NUMBER_PCH_SPI << 19) | (PCI_FUNCTION_NUMBER_PCH_SPI << 16) | R_PCH_SPI_BC ) } }, S_PCH_SPI_BC, N_PCH_SPI_BC_BLE }, }, { { { PCIE_ADDR_TYPE, { ( (DEFAULT_PCI_BUS_NUMBER_PCH << 24) | (PCI_DEVICE_NUMBER_PCH_SPI << 19) | (PCI_FUNCTION_NUMBER_PCH_SPI << 16) | R_PCH_SPI_BC ) } }, S_PCH_SPI_BC, N_PCH_SPI_BC_SYNC_SS } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_TCO } }; /** Special handling for SPI Write Protect @param[in] SrcDesc Not used **/ VOID EFIAPI PchTcoSpiWpClearSource ( PCH_SMM_SOURCE_DESC *SrcDesc ) { UINTN SpiRegBase; SpiRegBase = MmPciBase ( DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SPI, PCI_FUNCTION_NUMBER_PCH_SPI ); MmioAndThenOr32 ( SpiRegBase + R_PCH_SPI_BC, (UINT32) ~B_PCH_SPI_BC_ASYNC_SS, B_PCH_SPI_BC_SYNC_SS ); // // 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); } /** Special handling to enable SPI Write Protect **/ VOID PchTcoSpiWpEnableSource ( VOID ) { UINTN SpiRegBase; SpiRegBase = MmPciBase ( DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SPI, PCI_FUNCTION_NUMBER_PCH_SPI ); MmioAndThenOr32 ( SpiRegBase + R_PCH_SPI_BC, (UINT32) ~(B_PCH_SPI_BC_ASYNC_SS | B_PCH_SPI_BC_SYNC_SS), B_PCH_SPI_BC_LE ); IoOr32 (mAcpiBaseAddr + R_PCH_SMI_EN, B_PCH_SMI_EN_TCO); // // Clear the source // PchTcoSpiWpClearSource (NULL); } /** 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 ( &gPchTcoSmiDispatchProtocolGuid, &mSrcDescSpiBiosWp, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchTcoSmiSpiBiosWpType, DispatchHandle ); if (!EFI_ERROR (Status)) { Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle); Record->ClearSource = PchTcoSpiWpClearSource; PchTcoSpiWpClearSource (NULL); PchTcoSpiWpEnableSource (); } return Status; } // // LpcBiosWp srcdesc // PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_TCO }, { { PCIE_ADDR_TYPE, { ( (DEFAULT_PCI_BUS_NUMBER_PCH << 24) | (PCI_DEVICE_NUMBER_PCH_LPC << 19) | (PCI_FUNCTION_NUMBER_PCH_LPC << 16) | R_PCH_LPC_BC ) } }, S_PCH_LPC_BC, N_PCH_LPC_BC_LE } }, { { { TCO_ADDR_TYPE, {R_PCH_TCO1_STS} }, S_PCH_TCO1_STS, N_PCH_TCO1_STS_BIOSWR } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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; } Status = PchSmiRecordInsert ( &gPchTcoSmiDispatchProtocolGuid, &mSrcDescLpcBiosWp, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchTcoSmiLpcBiosWpType, DispatchHandle ); if (!EFI_ERROR (Status)) { Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle); Record->ClearSource = PchTcoSmiClearSource; PchSmmClearSource (&Record->SrcDesc); PchSmmEnableSource (&Record->SrcDesc); } return Status; } // // NEWCENTURY_STS bit that needs to be cleared // PCH_SMM_SOURCE_DESC mSrcDescNewCentury = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_TCO }, NULL_BIT_DESC_INITIALIZER }, { { { TCO_ADDR_TYPE, {R_PCH_TCO1_STS} }, S_PCH_TCO1_STS, N_PCH_TCO1_STS_NEWCENTURY } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_TCO } }; /** Check and clear NEWCENTURY_STS. It will clear the SMI status once it happens. @param[in] SrcDesc Pointer to the PCH SMI source description table **/ VOID EFIAPI PchTcoClearNewCenturySts ( PCH_SMM_SOURCE_DESC *SrcDesc ) { UINT16 TcoSts1; TcoSts1 = IoRead16 (mTcoBaseAddr + R_PCH_TCO1_STS); if (TcoSts1 & B_PCH_TCO1_STS_NEWCENTURY) { PchTcoSmiClearSourceAndBlock (&mSrcDescNewCentury); } } /** 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 ( &gPchTcoSmiDispatchProtocolGuid, &mSrcDescNewCentury, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchTcoSmiNewCenturyType, DispatchHandle ); if (!EFI_ERROR (Status)) { Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle); Record->ClearSource = PchTcoClearNewCenturySts; PchTcoClearNewCenturySts (&Record->SrcDesc); PchSmmEnableSource (&Record->SrcDesc); } 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; 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 == PCI_DEVICE_NUMBER_PCH_SPI) && (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_SPI) && (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_PCH_SPI_BC) && (Record->SrcDesc.En[1].Bit == N_PCH_SPI_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 == PCI_DEVICE_NUMBER_PCH_LPC) && (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_LPC) && (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_PCH_LPC_BC) && (Record->SrcDesc.En[1].Bit == N_PCH_LPC_BC_LE)) { // // eSPI/LPC Write Protect cannot be disabled // return EFI_ACCESS_DENIED; } return PchSmiRecordUnRegister (DispatchHandle); } // // PcieRpHotPlug srcdesc // PCH_SMM_SOURCE_DESC PchPcieSmiRpHotPlugTemplate = { PCH_SMM_NO_FLAGS, { { { PCIE_ADDR_TYPE, {R_PCH_PCIE_MPC} }, S_PCH_PCIE_MPC, N_PCH_PCIE_MPC_HPME }, NULL_BIT_DESC_INITIALIZER }, { { { PCIE_ADDR_TYPE, {R_PCH_PCIE_SMSCS} }, S_PCH_PCIE_SMSCS, N_PCH_PCIE_SMSCS_HPPDM } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_PCI_EXP } }; /** 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 Indicate the RP index (0-based) @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; // // 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; } GetPchPcieRpDevFun (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 ( &gPchPcieSmiDispatchProtocolGuid, &PchPcieSmiRpHotPlugTemplate, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchPcieSmiRpHotplugType, DispatchHandle ); PchSmmClearSource (&PchPcieSmiRpHotPlugTemplate); PchSmmEnableSource (&PchPcieSmiRpHotPlugTemplate); return Status; } // // PcieRpLinkActive srcdesc // PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkActiveTemplate = { PCH_SMM_NO_FLAGS, { { { PCIE_ADDR_TYPE, {R_PCH_PCIE_MPC} }, S_PCH_PCIE_MPC, N_PCH_PCIE_MPC_HPME }, NULL_BIT_DESC_INITIALIZER }, { { { PCIE_ADDR_TYPE, {R_PCH_PCIE_SMSCS} }, S_PCH_PCIE_SMSCS, N_PCH_PCIE_SMSCS_HPLAS } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_PCI_EXP } }; /** 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 Indicate the RP index (0-based) @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; // // 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; } GetPchPcieRpDevFun (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 ( &gPchPcieSmiDispatchProtocolGuid, &PchPcieSmiRpLinkActiveTemplate, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchPcieSmiRpLinkActiveType, DispatchHandle ); PchSmmClearSource (&PchPcieSmiRpLinkActiveTemplate); PchSmmEnableSource (&PchPcieSmiRpLinkActiveTemplate); return Status; } // // PcieRpLinkEq srcdesc // PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkEqTemplate = { PCH_SMM_NO_FLAGS, { { { PCIE_ADDR_TYPE, {R_PCH_PCIE_EQCFG1} }, S_PCH_PCIE_EQCFG1, N_PCH_PCIE_EQCFG1_LERSMIE }, NULL_BIT_DESC_INITIALIZER }, { { { PCIE_ADDR_TYPE, {R_PCH_PCIE_SMSCS} }, S_PCH_PCIE_SMSCS, N_PCH_PCIE_SMSCS_LERSMIS } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_PCI_EXP } }; /** 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 Indicate the RP index (0-based) @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; // // 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; } GetPchPcieRpDevFun (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; return PchSmiRecordInsert ( &gPchPcieSmiDispatchProtocolGuid, &PchPcieSmiRpLinkEqTemplate, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchPcieSmiRpLinkEqType, DispatchHandle ); } /** 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 ) { return PchSmiRecordUnRegister (DispatchHandle); } // // Pme srcdesc // PCH_SMM_SOURCE_DESC mSrcDescPme = { PCH_SMM_SCI_EN_DEPENDENT, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_GPE0_EN_127_96} }, S_PCH_ACPI_GPE0_EN_127_96, N_PCH_ACPI_GPE0_EN_127_96_PME }, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_GPE0_STS_127_96} }, S_PCH_ACPI_GPE0_STS_127_96, N_PCH_ACPI_GPE0_STS_127_96_PME } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchAcpiSmiDispatchProtocolGuid, &mSrcDescPme, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchAcpiSmiPmeType, DispatchHandle ); PchSmmClearSource (&mSrcDescPme); PchSmmEnableSource (&mSrcDescPme); return Status; } // // PmeB0 srcdesc // PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = { PCH_SMM_SCI_EN_DEPENDENT, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_GPE0_EN_127_96} }, S_PCH_ACPI_GPE0_EN_127_96, N_PCH_ACPI_GPE0_EN_127_96_PME_B0 }, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_GPE0_STS_127_96} }, S_PCH_ACPI_GPE0_STS_127_96, N_PCH_ACPI_GPE0_STS_127_96_PME_B0 } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchAcpiSmiDispatchProtocolGuid, &mSrcDescPmeB0, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchAcpiSmiPmeB0Type, DispatchHandle ); PchSmmClearSource (&mSrcDescPmeB0); PchSmmEnableSource (&mSrcDescPmeB0); return Status; } // // RtcAlarm srcdesc // PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = { PCH_SMM_SCI_EN_DEPENDENT, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_PM1_EN} }, S_PCH_ACPI_PM1_EN, N_PCH_ACPI_PM1_EN_RTC }, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_PM1_STS} }, S_PCH_ACPI_PM1_STS, N_PCH_ACPI_PM1_STS_RTC } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchAcpiSmiDispatchProtocolGuid, &mSrcDescRtcAlarm, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchAcpiSmiRtcAlarmType, DispatchHandle ); PchSmmClearSource (&mSrcDescRtcAlarm); PchSmmEnableSource (&mSrcDescRtcAlarm); return Status; } // // TmrOverflow srcdesc // PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = { PCH_SMM_SCI_EN_DEPENDENT, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_PM1_EN} }, S_PCH_ACPI_PM1_EN, N_PCH_ACPI_PM1_EN_TMROF }, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_ACPI_PM1_STS} }, S_PCH_ACPI_PM1_STS, N_PCH_ACPI_PM1_STS_TMROF } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchAcpiSmiDispatchProtocolGuid, &mSrcDescTmrOverflow, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchAcpiSmiTmrOverflowType, DispatchHandle ); PchSmmClearSource (&mSrcDescTmrOverflow); PchSmmEnableSource (&mSrcDescTmrOverflow); 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 ) { return PchSmiRecordUnRegister (DispatchHandle); } // // GpioUnlock srcdesc // PCH_SMM_SOURCE_DESC mSrcDescGpioUnlock = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_GPIO_UNLOCK }, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_GPIO_UNLOCK } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_GPIO_UNLOCK } }; /** The register function used to register SMI handler of GPIO Unlock 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 PchGpioUnlockSmiRegister ( IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This, IN PCH_GPIO_UNLOCK_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 ( &gPchGpioUnlockSmiDispatchProtocolGuid, &mSrcDescGpioUnlock, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchGpioUnlockSmiType, DispatchHandle ); PchSmmClearSource (&mSrcDescGpioUnlock); PchSmmEnableSource (&mSrcDescGpioUnlock); return Status; } /** Unregister a child SMI source dispatch function with a parent GPIO UNLOCK 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 PchGpioUnlockSmiUnRegister ( IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This, IN EFI_HANDLE DispatchHandle ) { return PchSmiRecordUnRegister (DispatchHandle); } // // SerialIrq srcdesc // PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = { PCH_SMM_NO_FLAGS, { NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_SERIRQ } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchSmiDispatchProtocolGuid, &mSrcDescSerialIrq, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchSmiSerialIrqType, DispatchHandle ); PchSmmClearSource (&mSrcDescSerialIrq); PchSmmEnableSource (&mSrcDescSerialIrq); return Status; } // // McSmi srcdesc // PCH_SMM_SOURCE_DESC mSrcDescMcSmi = { PCH_SMM_NO_FLAGS, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_EN} }, S_PCH_SMI_EN, N_PCH_SMI_EN_MCSMI }, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_MCSMI } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchSmiDispatchProtocolGuid, &mSrcDescMcSmi, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchSmiMcSmiType, DispatchHandle ); PchSmmClearSource (&mSrcDescMcSmi); PchSmmEnableSource (&mSrcDescMcSmi); return Status; } // // SmBus srcdesc // PCH_SMM_SOURCE_DESC mSrcDescSmbus = { PCH_SMM_NO_FLAGS, { NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER }, { { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_SMBUS } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( &gPchSmiDispatchProtocolGuid, &mSrcDescSmbus, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchSmiSmBusType, DispatchHandle ); PchSmmClearSource (&mSrcDescSmbus); PchSmmEnableSource (&mSrcDescSmbus); return Status; } // // SpiAsyncSmi srcdesc // PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = { PCH_SMM_NO_FLAGS, { { { PCIE_ADDR_TYPE, { ( (DEFAULT_PCI_BUS_NUMBER_PCH << 24) | (PCI_DEVICE_NUMBER_PCH_SPI << 19) | (PCI_FUNCTION_NUMBER_PCH_SPI << 16) | R_PCH_SPI_BC ) } }, S_PCH_SPI_BC, N_PCH_SPI_BC_ASE_BWP }, NULL_BIT_DESC_INITIALIZER }, { { { PCIE_ADDR_TYPE, { ( (DEFAULT_PCI_BUS_NUMBER_PCH << 24) | (PCI_DEVICE_NUMBER_PCH_SPI << 19) | (PCI_FUNCTION_NUMBER_PCH_SPI << 16) | R_PCH_SPI_BC ) } }, S_PCH_SPI_BC, N_PCH_SPI_BC_ASYNC_SS } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( PCH_SMM_SOURCE_DESC *SrcDesc ) { UINTN SpiRegBase; UINT32 SpiBar0; SpiRegBase = MmPciBase ( DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SPI, PCI_FUNCTION_NUMBER_PCH_SPI ); SpiBar0 = MmioRead32 (SpiRegBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_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; MmioAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE); MmioWrite32 (SpiRegBase + R_PCH_SPI_BAR0, SpiBar0); MmioOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE); } MmioOr32 (SpiBar0 + R_PCH_SPI_HSFSC, B_PCH_SPI_HSFSC_FDONE); } /** Special handling to enable SPI Asynchronous SMI **/ VOID PchSmiSpiAsyncEnableSource ( VOID ) { UINTN SpiRegBase; SpiRegBase = MmPciBase ( DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SPI, PCI_FUNCTION_NUMBER_PCH_SPI ); MmioAndThenOr32 ( SpiRegBase + R_PCH_SPI_BC, (UINT32) ~B_PCH_SPI_BC_SYNC_SS, B_PCH_SPI_BC_ASE_BWP ); // // 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 ( &gPchSmiDispatchProtocolGuid, &mSrcDescSpiAsyncSmi, (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction, PchSmiSpiAsyncType, DispatchHandle ); if (!EFI_ERROR (Status)) { Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle); Record->ClearSource = PchSmiSpiAsyncClearSource; PchSmiSpiAsyncClearSource (NULL); PchSmiSpiAsyncEnableSource (); } 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; UINTN SpiRegBase; 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 == PCI_DEVICE_NUMBER_PCH_SPI) && (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_SPI) && (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_PCH_SPI_BC) && (Record->SrcDesc.En[0].Bit == N_PCH_SPI_BC_ASE_BWP)) { SpiRegBase = MmPciBase ( DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SPI, PCI_FUNCTION_NUMBER_PCH_SPI ); if (MmioRead8 (SpiRegBase + R_PCH_SPI_BC) & B_PCH_SPI_BC_BILD) { // // SPI Asynchronous SMI cannot be disabled // return EFI_ACCESS_DENIED; } } return PchSmiRecordUnRegister (DispatchHandle); } /** 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 PCH GPIO UNLOCK SMI DISPATCH PROTOCOL instance **/ PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL mPchGpioUnlockSmiDispatchProtocol = { PCH_GPIO_UNLOCK_SMI_DISPATCH_REVISION,// Revision PchGpioUnlockSmiUnRegister, // Unregister PchGpioUnlockSmiRegister // GpioUnlock }; /** 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 ); Status = gSmst->SmmInstallProtocolInterface ( &Handle, &gPchPcieSmiDispatchProtocolGuid, EFI_NATIVE_INTERFACE, &mPchPcieSmiDispatchProtocol ); Status = gSmst->SmmInstallProtocolInterface ( &Handle, &gPchAcpiSmiDispatchProtocolGuid, EFI_NATIVE_INTERFACE, &mPchAcpiSmiDispatchProtocol ); Status = gSmst->SmmInstallProtocolInterface ( &Handle, &gPchGpioUnlockSmiDispatchProtocolGuid, EFI_NATIVE_INTERFACE, &mPchGpioUnlockSmiDispatchProtocol ); 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; GetPchPcieRpNumber (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 PchGpioUnlockSmiType: ((PCH_GPIO_UNLOCK_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; } 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_PCH_PCR_PSTH_TRPREG0) } }, 4, 0 }, NULL_BIT_DESC_INITIALIZER }, { { { PCR_ADDR_TYPE, {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) } }, 1, 0 } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_MONITOR } }, // // PCH I/O Trap register 1 monitor // { PCH_SMM_NO_FLAGS, { { { PCR_ADDR_TYPE, {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG1) } }, 4, 0 }, NULL_BIT_DESC_INITIALIZER }, { { { PCR_ADDR_TYPE, {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) } }, 1, 1 } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_MONITOR } }, // // PCH I/O Trap register 2 monitor // { PCH_SMM_NO_FLAGS, { { { PCR_ADDR_TYPE, {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG2) } }, 4, 0 }, NULL_BIT_DESC_INITIALIZER }, { { { PCR_ADDR_TYPE, {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) } }, 1, 2 } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_SMI_STS_MONITOR } }, // // PCH I/O Trap register 3 monitor, // { PCH_SMM_NO_FLAGS, { { { PCR_ADDR_TYPE, {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG3) } }, 4, 0 }, NULL_BIT_DESC_INITIALIZER }, { { { PCR_ADDR_TYPE, {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) } }, 1, 3 } }, { { ACPI_ADDR_TYPE, {R_PCH_SMI_STS} }, S_PCH_SMI_STS, N_PCH_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 ( NULL, &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); }