+++ /dev/null
-/** @file\r
- SMM SwDispatch2 Protocol on SMM SwDispatch Protocol Thunk driver.\r
-\r
- Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
- \r\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
- \r\r
-\r
-**/\r
-\r
-#include <PiDxe.h>\r
-#include <FrameworkSmm.h>\r
-\r
-#include <Protocol/SmmSwDispatch2.h>\r
-#include <Protocol/SmmSwDispatch.h>\r
-#include <Protocol/SmmControl.h>\r
-#include <Protocol/SmmCpu.h>\r
-\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/SmmServicesTableLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/DebugLib.h>\r
-\r
-typedef struct {\r
- LIST_ENTRY Link;\r
- EFI_HANDLE DispatchHandle;\r
- UINTN SwSmiInputValue;\r
- UINTN DispatchFunction;\r
-} EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT;\r
-\r
-/**\r
- Register a child SMI source dispatch function for the specified software SMI.\r
-\r
- This service registers a function (DispatchFunction) which will be called when the software\r
- SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,\r
- DispatchHandle contains a unique handle which may be used later to unregister the function\r
- using UnRegister().\r
-\r
- @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.\r
- @param[in] DispatchFunction Function to register for handler when the specified software\r
- SMI is generated.\r
- @param[in, out] RegisterContext Pointer to the dispatch function's context.\r
- The caller fills this context in before calling\r
- the register function to indicate to the register\r
- function which Software SMI input value the\r
- dispatch function should be invoked for.\r
- @param[out] DispatchHandle Handle generated by the dispatcher to track the\r
- function instance.\r
-\r
- @retval EFI_SUCCESS The dispatch function has been successfully\r
- registered and the SMI source has been enabled.\r
- @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source.\r
- @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value\r
- is not within valid range.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this\r
- child.\r
- @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned\r
- for this dispatch.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmSwDispatch2Register (\r
- IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,\r
- IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,\r
- IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext,\r
- OUT EFI_HANDLE *DispatchHandle\r
- );\r
-\r
-/**\r
- Unregister a child SMI source dispatch function for the specified software SMI.\r
-\r
- This service removes the handler associated with DispatchHandle so that it will no longer be\r
- called in response to a software SMI.\r
-\r
- @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.\r
- @param[in] DispatchHandle Handle of dispatch function to deregister.\r
-\r
- @retval EFI_SUCCESS The dispatch function has been successfully unregistered.\r
- @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmSwDispatch2UnRegister (\r
- IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,\r
- IN EFI_HANDLE DispatchHandle\r
- );\r
-\r
-EFI_SMM_SW_DISPATCH2_PROTOCOL gSmmSwDispatch2 = {\r
- SmmSwDispatch2Register,\r
- SmmSwDispatch2UnRegister,\r
- 0 // MaximumSwiValue\r
-};\r
-\r
-EFI_SMM_SW_DISPATCH_PROTOCOL *mSmmSwDispatch;\r
-UINT8 mSmiTriggerRegister;\r
-UINT8 mSmiDataRegister;\r
-\r
-EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;\r
-LIST_ENTRY mSmmSwDispatch2ThunkQueue = INITIALIZE_LIST_HEAD_VARIABLE (mSmmSwDispatch2ThunkQueue);\r
-\r
-/**\r
- This function find SmmSwDispatch2Context by SwSmiInputValue.\r
-\r
- @param SwSmiInputValue The SwSmiInputValue to indentify the SmmSwDispatch2 context\r
-\r
- @return SmmSwDispatch2 context\r
-**/\r
-EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *\r
-FindSmmSwDispatch2ContextBySwSmiInputValue (\r
- IN UINTN SwSmiInputValue\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext;\r
-\r
- for (Link = mSmmSwDispatch2ThunkQueue.ForwardLink;\r
- Link != &mSmmSwDispatch2ThunkQueue;\r
- Link = Link->ForwardLink) {\r
- ThunkContext = BASE_CR (\r
- Link,\r
- EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT,\r
- Link\r
- );\r
- if (ThunkContext->SwSmiInputValue == SwSmiInputValue) {\r
- return ThunkContext;\r
- }\r
- }\r
- return NULL;\r
-}\r
-\r
-/**\r
- This function find SmmSwDispatch2Context by DispatchHandle.\r
-\r
- @param DispatchHandle The DispatchHandle to indentify the SmmSwDispatch2Thunk context\r
-\r
- @return SmmSwDispatch2Thunk context\r
-**/\r
-EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *\r
-FindSmmSwDispatch2ContextByDispatchHandle (\r
- IN EFI_HANDLE DispatchHandle\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext;\r
-\r
- for (Link = mSmmSwDispatch2ThunkQueue.ForwardLink;\r
- Link != &mSmmSwDispatch2ThunkQueue;\r
- Link = Link->ForwardLink) {\r
- ThunkContext = BASE_CR (\r
- Link,\r
- EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT,\r
- Link\r
- );\r
- if (ThunkContext->DispatchHandle == DispatchHandle) {\r
- return ThunkContext;\r
- }\r
- }\r
- return NULL;\r
-}\r
-\r
-/**\r
- Framework dispatch function for a Software SMI handler.\r
-\r
- @param DispatchHandle The handle of this dispatch function.\r
- @param DispatchContext The pointer to the dispatch function's context.\r
- The SwSmiInputValue field is filled in\r
- by the software dispatch driver prior to\r
- invoking this dispatch function.\r
- The dispatch function will only be called\r
- for input values for which it is registered.\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-FrameworkDispatchFunction (\r
- IN EFI_HANDLE DispatchHandle,\r
- IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext\r
- )\r
-{\r
- EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext;\r
- EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction;\r
- EFI_SMM_SW_REGISTER_CONTEXT RegisterContext;\r
- EFI_SMM_SW_CONTEXT SwContext;\r
- UINTN Size;\r
- UINTN Index;\r
- EFI_SMM_SAVE_STATE_IO_INFO IoInfo;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Search context\r
- //\r
- ThunkContext = FindSmmSwDispatch2ContextBySwSmiInputValue (DispatchContext->SwSmiInputValue);\r
- ASSERT (ThunkContext != NULL);\r
- if (ThunkContext == NULL) {\r
- return ;\r
- }\r
-\r
- //\r
- // Construct new context\r
- //\r
- RegisterContext.SwSmiInputValue = DispatchContext->SwSmiInputValue;\r
- Size = sizeof(SwContext);\r
- SwContext.CommandPort = IoRead8 (mSmiTriggerRegister);\r
- SwContext.DataPort = IoRead8 (mSmiDataRegister);\r
-\r
- //\r
- // Try to find which CPU trigger SWSMI\r
- //\r
- SwContext.SwSmiCpuIndex = 0;\r
- for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
- Status = mSmmCpuProtocol->ReadSaveState (\r
- mSmmCpuProtocol,\r
- sizeof(IoInfo),\r
- EFI_SMM_SAVE_STATE_REGISTER_IO,\r
- Index,\r
- &IoInfo\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
- if (IoInfo.IoPort == mSmiTriggerRegister) {\r
- //\r
- // Great! Find it.\r
- //\r
- SwContext.SwSmiCpuIndex = Index;\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Dispatch\r
- //\r
- DispatchFunction = (EFI_SMM_HANDLER_ENTRY_POINT2)ThunkContext->DispatchFunction;\r
- DispatchFunction (\r
- DispatchHandle,\r
- &RegisterContext,\r
- &SwContext,\r
- &Size\r
- );\r
- return ;\r
-}\r
-\r
-/**\r
- Register a child SMI source dispatch function for the specified software SMI.\r
-\r
- This service registers a function (DispatchFunction) which will be called when the software\r
- SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,\r
- DispatchHandle contains a unique handle which may be used later to unregister the function\r
- using UnRegister().\r
-\r
- @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.\r
- @param[in] DispatchFunction Function to register for handler when the specified software\r
- SMI is generated.\r
- @param[in, out] RegisterContext Pointer to the dispatch function's context.\r
- The caller fills this context in before calling\r
- the register function to indicate to the register\r
- function which Software SMI input value the\r
- dispatch function should be invoked for.\r
- @param[out] DispatchHandle Handle generated by the dispatcher to track the\r
- function instance.\r
-\r
- @retval EFI_SUCCESS The dispatch function has been successfully\r
- registered and the SMI source has been enabled.\r
- @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source.\r
- @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value\r
- is not within valid range.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this\r
- child.\r
- @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned\r
- for this dispatch.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmSwDispatch2Register (\r
- IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,\r
- IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,\r
- IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext,\r
- OUT EFI_HANDLE *DispatchHandle\r
- )\r
-{\r
- EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext;\r
- EFI_SMM_SW_DISPATCH_CONTEXT DispatchContext;\r
- EFI_STATUS Status;\r
- UINTN Index;\r
-\r
- if (RegisterContext->SwSmiInputValue == (UINTN)-1) {\r
- //\r
- // If SwSmiInputValue is set to (UINTN) -1 then a unique value will be assigned and returned in the structure.\r
- //\r
- Status = EFI_NOT_FOUND;\r
- for (Index = 1; Index < gSmmSwDispatch2.MaximumSwiValue; Index++) {\r
- DispatchContext.SwSmiInputValue = Index;\r
- Status = mSmmSwDispatch->Register (\r
- mSmmSwDispatch,\r
- FrameworkDispatchFunction,\r
- &DispatchContext,\r
- DispatchHandle\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- RegisterContext->SwSmiInputValue = Index;\r
- break;\r
- }\r
- }\r
- if (RegisterContext->SwSmiInputValue == (UINTN)-1) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- DispatchContext.SwSmiInputValue = RegisterContext->SwSmiInputValue;\r
- Status = mSmmSwDispatch->Register (\r
- mSmmSwDispatch,\r
- FrameworkDispatchFunction,\r
- &DispatchContext,\r
- DispatchHandle\r
- );\r
- }\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Register\r
- //\r
- Status = gSmst->SmmAllocatePool (\r
- EfiRuntimeServicesData,\r
- sizeof(*ThunkContext),\r
- (VOID **)&ThunkContext\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- mSmmSwDispatch->UnRegister (mSmmSwDispatch, *DispatchHandle);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- ThunkContext->SwSmiInputValue = RegisterContext->SwSmiInputValue;\r
- ThunkContext->DispatchFunction = (UINTN)DispatchFunction;\r
- ThunkContext->DispatchHandle = *DispatchHandle;\r
- InsertTailList (&mSmmSwDispatch2ThunkQueue, &ThunkContext->Link);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Unregister a child SMI source dispatch function for the specified software SMI.\r
-\r
- This service removes the handler associated with DispatchHandle so that it will no longer be\r
- called in response to a software SMI.\r
-\r
- @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.\r
- @param[in] DispatchHandle Handle of dispatch function to deregister.\r
-\r
- @retval EFI_SUCCESS The dispatch function has been successfully unregistered.\r
- @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmSwDispatch2UnRegister (\r
- IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,\r
- IN EFI_HANDLE DispatchHandle\r
- )\r
-{\r
- EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext;\r
- EFI_STATUS Status;\r
-\r
- Status = mSmmSwDispatch->UnRegister (mSmmSwDispatch, DispatchHandle);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Unregister\r
- //\r
- ThunkContext = FindSmmSwDispatch2ContextByDispatchHandle (DispatchHandle);\r
- ASSERT (ThunkContext != NULL);\r
- if (ThunkContext != NULL) {\r
- RemoveEntryList (&ThunkContext->Link);\r
- gSmst->SmmFreePool (ThunkContext);\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Entry Point for this thunk driver.\r
-\r
- @param[in] ImageHandle Image handle of this driver.\r
- @param[in] SystemTable A Pointer to the EFI System Table.\r
-\r
- @retval EFI_SUCCESS The entry point is executed successfully.\r
- @retval other Some error occurred when executing this entry point.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmSwDispatch2ThunkMain (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_SMM_CONTROL_PROTOCOL *SmmControl;\r
- EFI_SMM_CONTROL_REGISTER RegisterInfo;\r
-\r
- //\r
- // Locate Framework SMM SwDispatch Protocol\r
- //\r
- Status = gBS->LocateProtocol (\r
- &gEfiSmmSwDispatchProtocolGuid,\r
- NULL,\r
- (VOID **)&mSmmSwDispatch\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- gSmmSwDispatch2.MaximumSwiValue = mSmmSwDispatch->MaximumSwiValue;\r
- if (gSmmSwDispatch2.MaximumSwiValue == 0x0) {\r
- DEBUG ((EFI_D_ERROR, "BUGBUG: MaximumSwiValue is 0, work-around to make it 0xFF\n"));\r
- gSmmSwDispatch2.MaximumSwiValue = 0xFF;\r
- }\r
-\r
- //\r
- // Locate Framework SMM Control Protocol\r
- //\r
- Status = gBS->LocateProtocol (\r
- &gEfiSmmControlProtocolGuid,\r
- NULL,\r
- (VOID **)&SmmControl\r
- );\r
-\r
- ASSERT_EFI_ERROR (Status);\r
- Status = SmmControl->GetRegisterInfo (\r
- SmmControl,\r
- &RegisterInfo\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- mSmiTriggerRegister = RegisterInfo.SmiTriggerRegister;\r
- mSmiDataRegister = RegisterInfo.SmiDataRegister;\r
-\r
- //\r
- // Locate PI SMM CPU protocol\r
- //\r
- Status = gSmst->SmmLocateProtocol (\r
- &gEfiSmmCpuProtocolGuid,\r
- NULL,\r
- (VOID **)&mSmmCpuProtocol\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Publish PI SMM SwDispatch2 Protocol\r
- //\r
- ImageHandle = NULL;\r
- Status = gSmst->SmmInstallProtocolInterface (\r
- &ImageHandle,\r
- &gEfiSmmSwDispatch2ProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &gSmmSwDispatch2\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- return Status;\r
-}\r
-\r