From 1528075ab09cdf18e866dca86791535eebb1949e Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Fri, 23 Dec 2016 13:55:44 +0800 Subject: BroxtonPlatformPkg: Add SmmSwDispatch2OnSmmSwDispatchThunk Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../SmmSwDispatch2OnSmmSwDispatchThunk.c | 456 +++++++++++++++++++++ .../SmmSwDispatch2OnSmmSwDispatchThunk.inf | 54 +++ 2 files changed, 510 insertions(+) create mode 100644 Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf diff --git a/Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c b/Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c new file mode 100644 index 0000000000..f3679e10af --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c @@ -0,0 +1,456 @@ +/** @file + SMM SwDispatch2 Protocol on SMM SwDispatch Protocol Thunk driver. + + Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + LIST_ENTRY Link; + EFI_HANDLE DispatchHandle; + UINTN SwSmiInputValue; + UINTN DispatchFunction; +} EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT; + + +/** + Register a child SMI source dispatch function for the specified software SMI. + + This service registers a function (DispatchFunction) which will be called when the software + SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified software + SMI is generated. + @param[in, out] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function which Software SMI input value the + dispatch function should be invoked for. + @param[out] DispatchHandle Handle generated by the dispatcher to track the + function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this + child. + @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned + for this dispatch. + +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2Register ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction, + IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + + +/** + Unregister a child SMI source dispatch function for the specified software SMI. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called in response to a software SMI. + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. + +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2UnRegister ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +EFI_SMM_SW_DISPATCH2_PROTOCOL gSmmSwDispatch2 = { + SmmSwDispatch2Register, + SmmSwDispatch2UnRegister, + 0 // MaximumSwiValue +}; + +EFI_SMM_SW_DISPATCH_PROTOCOL *mSmmSwDispatch; +UINT8 mSmiTriggerRegister; +UINT8 mSmiDataRegister; + +EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol; +LIST_ENTRY mSmmSwDispatch2ThunkQueue = INITIALIZE_LIST_HEAD_VARIABLE (mSmmSwDispatch2ThunkQueue); + + +/** + This function find SmmSwDispatch2Context by SwSmiInputValue. + + @param[in] SwSmiInputValue The SwSmiInputValue to indentify the SmmSwDispatch2 context + + @return SmmSwDispatch2 context + +**/ +EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT * +FindSmmSwDispatch2ContextBySwSmiInputValue ( + IN UINTN SwSmiInputValue + ) +{ + LIST_ENTRY *Link; + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + + for (Link = mSmmSwDispatch2ThunkQueue.ForwardLink; + Link != &mSmmSwDispatch2ThunkQueue; + Link = Link->ForwardLink) { + ThunkContext = BASE_CR ( + Link, + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT, + Link + ); + if (ThunkContext->SwSmiInputValue == SwSmiInputValue) { + return ThunkContext; + } + } + + return NULL; +} + + +/** + This function find SmmSwDispatch2Context by DispatchHandle. + + @param[in] DispatchHandle The DispatchHandle to indentify the SmmSwDispatch2Thunk context + + @return SmmSwDispatch2Thunk context + +**/ +EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT * +FindSmmSwDispatch2ContextByDispatchHandle ( + IN EFI_HANDLE DispatchHandle + ) +{ + LIST_ENTRY *Link; + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + + for (Link = mSmmSwDispatch2ThunkQueue.ForwardLink; + Link != &mSmmSwDispatch2ThunkQueue; + Link = Link->ForwardLink) { + ThunkContext = BASE_CR ( + Link, + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT, + Link + ); + if (ThunkContext->DispatchHandle == DispatchHandle) { + return ThunkContext; + } + } + + return NULL; +} + + +/** + Framework dispatch function for a Software SMI handler. + + @param[in] DispatchHandle The handle of this dispatch function. + @param[in] DispatchContext The pointer to the dispatch function's context. + The SwSmiInputValue field is filled in + by the software dispatch driver prior to + invoking this dispatch function. + The dispatch function will only be called + for input values for which it is registered. + + @retval None + +**/ +VOID +EFIAPI +FrameworkDispatchFunction ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction; + EFI_SMM_SW_REGISTER_CONTEXT RegisterContext; + EFI_SMM_SW_CONTEXT SwContext; + UINTN Size; + UINTN Index; + EFI_SMM_SAVE_STATE_IO_INFO IoInfo; + EFI_STATUS Status; + + // + // Search context + // + ThunkContext = FindSmmSwDispatch2ContextBySwSmiInputValue (DispatchContext->SwSmiInputValue); + ASSERT (ThunkContext != NULL); + if (ThunkContext == NULL) { + return ; + } + + // + // Construct new context + // + RegisterContext.SwSmiInputValue = DispatchContext->SwSmiInputValue; + Size = sizeof (SwContext); + SwContext.CommandPort = IoRead8 (mSmiTriggerRegister); + SwContext.DataPort = IoRead8 (mSmiDataRegister); + + // + // Try to find which CPU trigger SWSMI + // + SwContext.SwSmiCpuIndex = 0; + for (Index = 0; Index < gSmst->NumberOfCpus; Index++) { + Status = mSmmCpuProtocol->ReadSaveState ( + mSmmCpuProtocol, + sizeof (IoInfo), + EFI_SMM_SAVE_STATE_REGISTER_IO, + Index, + &IoInfo + ); + if (EFI_ERROR (Status)) { + continue; + } + if (IoInfo.IoPort == mSmiTriggerRegister) { + // + // Great! Find it. + // + SwContext.SwSmiCpuIndex = Index; + break; + } + } + + // + // Dispatch + // + DispatchFunction = (EFI_SMM_HANDLER_ENTRY_POINT2) ThunkContext->DispatchFunction; + DispatchFunction ( + DispatchHandle, + &RegisterContext, + &SwContext, + &Size + ); + return ; +} + + +/** + Register a child SMI source dispatch function for the specified software SMI. + + This service registers a function (DispatchFunction) which will be called when the software + SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified software + SMI is generated. + @param[in, out] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function which Software SMI input value the + dispatch function should be invoked for. + @param[out] DispatchHandle Handle generated by the dispatcher to track the + function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this + child. + @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned + for this dispatch. + +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2Register ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction, + IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ) +{ + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + EFI_SMM_SW_DISPATCH_CONTEXT DispatchContext; + EFI_STATUS Status; + UINTN Index; + + if (RegisterContext->SwSmiInputValue == (UINTN)-1) { + // + // If SwSmiInputValue is set to (UINTN) -1 then a unique value will be assigned and returned in the structure. + // + Status = EFI_NOT_FOUND; + for (Index = 1; Index < gSmmSwDispatch2.MaximumSwiValue; Index++) { + DispatchContext.SwSmiInputValue = Index; + Status = mSmmSwDispatch->Register ( + mSmmSwDispatch, + FrameworkDispatchFunction, + &DispatchContext, + DispatchHandle + ); + if (!EFI_ERROR (Status)) { + RegisterContext->SwSmiInputValue = Index; + break; + } + } + if (RegisterContext->SwSmiInputValue == (UINTN)-1) { + return EFI_OUT_OF_RESOURCES; + } + } else { + DispatchContext.SwSmiInputValue = RegisterContext->SwSmiInputValue; + Status = mSmmSwDispatch->Register ( + mSmmSwDispatch, + FrameworkDispatchFunction, + &DispatchContext, + DispatchHandle + ); + } + if (!EFI_ERROR (Status)) { + // + // Register + // + Status = gSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + sizeof (*ThunkContext), + (VOID **) &ThunkContext + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + mSmmSwDispatch->UnRegister (mSmmSwDispatch, *DispatchHandle); + return EFI_OUT_OF_RESOURCES; + } + + ThunkContext->SwSmiInputValue = RegisterContext->SwSmiInputValue; + ThunkContext->DispatchFunction = (UINTN) DispatchFunction; + ThunkContext->DispatchHandle = *DispatchHandle; + InsertTailList (&mSmmSwDispatch2ThunkQueue, &ThunkContext->Link); + } + + return Status; +} + + +/** + Unregister a child SMI source dispatch function for the specified software SMI. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called in response to a software SMI. + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. + +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2UnRegister ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ) +{ + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + EFI_STATUS Status; + + Status = mSmmSwDispatch->UnRegister (mSmmSwDispatch, DispatchHandle); + if (!EFI_ERROR (Status)) { + // + // Unregister + // + ThunkContext = FindSmmSwDispatch2ContextByDispatchHandle (DispatchHandle); + ASSERT (ThunkContext != NULL); + if (ThunkContext != NULL) { + RemoveEntryList (&ThunkContext->Link); + gSmst->SmmFreePool (ThunkContext); + } + } + + return Status; +} + + +/** + Entry Point for this thunk driver. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable A Pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurred when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2ThunkMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Locate Framework SMM SwDispatch Protocol + // + Status = gBS->LocateProtocol (&gEfiSmmSwDispatchProtocolGuid, NULL, (VOID **) &mSmmSwDispatch); + ASSERT_EFI_ERROR (Status); + gSmmSwDispatch2.MaximumSwiValue = mSmmSwDispatch->MaximumSwiValue; + if (gSmmSwDispatch2.MaximumSwiValue == 0x0) { + DEBUG ((EFI_D_ERROR, "BUGBUG: MaximumSwiValue is 0, work-around to make it 0xFF\n")); + gSmmSwDispatch2.MaximumSwiValue = 0xFF; + } + + // + // Assign the R_APM_CNT and R_APM_STS to SWSMI Trigger port and Data Port + // + mSmiTriggerRegister = R_APM_CNT; + mSmiDataRegister = R_APM_STS; + + // + // Locate PI SMM CPU protocol + // + Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpuProtocol); + ASSERT_EFI_ERROR (Status); + + // + // Publish PI SMM SwDispatch2 Protocol + // + ImageHandle = NULL; + Status = gSmst->SmmInstallProtocolInterface ( + &ImageHandle, + &gEfiSmmSwDispatch2ProtocolGuid, + EFI_NATIVE_INTERFACE, + &gSmmSwDispatch2 + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf b/Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf new file mode 100644 index 0000000000..09082103ef --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Compatibility/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf @@ -0,0 +1,54 @@ +## @file +# Component description file for SMM SwDispatch2 Protocol on SMM SwDispatch Protocol Thunk driver. +# +# Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmSwDispatch2OnSmmSwDispatchThunk + FILE_GUID = 1410C6AC-9F4B-495b-9C23-8A5AEB0165E9 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = SmmSwDispatch2ThunkMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmSwDispatch2OnSmmSwDispatchThunk.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + SmmServicesTableLib + BaseLib + IoLib + DebugLib + +[Protocols] + gEfiSmmSwDispatchProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSmmCpuProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSmmSwDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[Depex] + gEfiSmmSwDispatchProtocolGuid AND + gEfiSmmCpuProtocolGuid -- cgit v1.2.3