summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Core/PiSmmCore/Smi.c
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Core/PiSmmCore/Smi.c
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Core/PiSmmCore/Smi.c')
-rw-r--r--MdeModulePkg/Core/PiSmmCore/Smi.c920
1 files changed, 460 insertions, 460 deletions
diff --git a/MdeModulePkg/Core/PiSmmCore/Smi.c b/MdeModulePkg/Core/PiSmmCore/Smi.c
index 6b56fa5f69..f3ab4bbd92 100644
--- a/MdeModulePkg/Core/PiSmmCore/Smi.c
+++ b/MdeModulePkg/Core/PiSmmCore/Smi.c
@@ -1,460 +1,460 @@
-/** @file
- SMI management.
-
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PiSmmCore.h"
-
-//
-// mSmiManageCallingDepth is used to track the depth of recursive calls of SmiManage.
-//
-UINTN mSmiManageCallingDepth = 0;
-
-LIST_ENTRY mSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mSmiEntryList);
-
-SMI_ENTRY mRootSmiEntry = {
- SMI_ENTRY_SIGNATURE,
- INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntry.AllEntries),
- { 0 },
- INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntry.SmiHandlers),
-};
-
-/**
- Finds the SMI entry for the requested handler type.
-
- @param HandlerType The type of the interrupt
- @param Create Create a new entry if not found
-
- @return SMI entry
-
-**/
-SMI_ENTRY *
-EFIAPI
-SmmCoreFindSmiEntry (
- IN EFI_GUID *HandlerType,
- IN BOOLEAN Create
- )
-{
- LIST_ENTRY *Link;
- SMI_ENTRY *Item;
- SMI_ENTRY *SmiEntry;
-
- //
- // Search the SMI entry list for the matching GUID
- //
- SmiEntry = NULL;
- for (Link = mSmiEntryList.ForwardLink;
- Link != &mSmiEntryList;
- Link = Link->ForwardLink)
- {
- Item = CR (Link, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
- if (CompareGuid (&Item->HandlerType, HandlerType)) {
- //
- // This is the SMI entry
- //
- SmiEntry = Item;
- break;
- }
- }
-
- //
- // If the protocol entry was not found and Create is TRUE, then
- // allocate a new entry
- //
- if ((SmiEntry == NULL) && Create) {
- SmiEntry = AllocatePool (sizeof (SMI_ENTRY));
- if (SmiEntry != NULL) {
- //
- // Initialize new SMI entry structure
- //
- SmiEntry->Signature = SMI_ENTRY_SIGNATURE;
- CopyGuid ((VOID *)&SmiEntry->HandlerType, HandlerType);
- InitializeListHead (&SmiEntry->SmiHandlers);
-
- //
- // Add it to SMI entry list
- //
- InsertTailList (&mSmiEntryList, &SmiEntry->AllEntries);
- }
- }
-
- return SmiEntry;
-}
-
-/**
- Remove SmiHandler and free the memory it used.
- If SmiEntry is empty, remove SmiEntry and free the memory it used.
-
- @param SmiHandler Points to SMI handler.
- @param SmiEntry Points to SMI Entry or NULL for root SMI handlers.
-
- @retval TRUE SmiEntry is removed.
- @retval FALSE SmiEntry is not removed.
-**/
-BOOLEAN
-RemoveSmiHandler (
- IN SMI_HANDLER *SmiHandler,
- IN SMI_ENTRY *SmiEntry
- )
-{
- ASSERT (SmiHandler->ToRemove);
- RemoveEntryList (&SmiHandler->Link);
- FreePool (SmiHandler);
-
- //
- // Remove the SMI_ENTRY if all handlers have been removed.
- //
- if (SmiEntry != NULL) {
- if (IsListEmpty (&SmiEntry->SmiHandlers)) {
- RemoveEntryList (&SmiEntry->AllEntries);
- FreePool (SmiEntry);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Manage SMI of a particular type.
-
- @param HandlerType Points to the handler type or NULL for root SMI handlers.
- @param Context Points to an optional context buffer.
- @param CommBuffer Points to the optional communication buffer.
- @param CommBufferSize Points to the size of the optional communication buffer.
-
- @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was processed successfully but not quiesced.
- @retval EFI_INTERRUPT_PENDING One or more SMI sources could not be quiesced.
- @retval EFI_NOT_FOUND Interrupt source was not handled or quiesced.
- @retval EFI_SUCCESS Interrupt source was handled and quiesced.
-
-**/
-EFI_STATUS
-EFIAPI
-SmiManage (
- IN CONST EFI_GUID *HandlerType,
- IN CONST VOID *Context OPTIONAL,
- IN OUT VOID *CommBuffer OPTIONAL,
- IN OUT UINTN *CommBufferSize OPTIONAL
- )
-{
- LIST_ENTRY *Link;
- LIST_ENTRY *Head;
- LIST_ENTRY *EntryLink;
- SMI_ENTRY *SmiEntry;
- SMI_HANDLER *SmiHandler;
- EFI_STATUS ReturnStatus;
- BOOLEAN WillReturn;
- EFI_STATUS Status;
-
- PERF_FUNCTION_BEGIN ();
- mSmiManageCallingDepth++;
- WillReturn = FALSE;
- Status = EFI_NOT_FOUND;
- ReturnStatus = Status;
- if (HandlerType == NULL) {
- //
- // Root SMI handler
- //
- SmiEntry = &mRootSmiEntry;
- } else {
- //
- // Non-root SMI handler
- //
- SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *)HandlerType, FALSE);
- if (SmiEntry == NULL) {
- //
- // There is no handler registered for this interrupt source
- //
- PERF_FUNCTION_END ();
- return Status;
- }
- }
-
- Head = &SmiEntry->SmiHandlers;
-
- for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
- SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
-
- Status = SmiHandler->Handler (
- (EFI_HANDLE)SmiHandler,
- Context,
- CommBuffer,
- CommBufferSize
- );
-
- switch (Status) {
- case EFI_INTERRUPT_PENDING:
- //
- // If a handler returns EFI_INTERRUPT_PENDING and HandlerType is not NULL then
- // no additional handlers will be processed and EFI_INTERRUPT_PENDING will be returned.
- //
- if (HandlerType != NULL) {
- PERF_FUNCTION_END ();
- ReturnStatus = EFI_INTERRUPT_PENDING;
- WillReturn = TRUE;
- } else {
- //
- // If any other handler's result sets ReturnStatus as EFI_SUCCESS, the return status
- // will be EFI_SUCCESS.
- //
- if (ReturnStatus != EFI_SUCCESS) {
- ReturnStatus = Status;
- }
- }
-
- break;
-
- case EFI_SUCCESS:
- //
- // If at least one of the handlers returns EFI_SUCCESS then the function will return
- // EFI_SUCCESS. If a handler returns EFI_SUCCESS and HandlerType is not NULL then no
- // additional handlers will be processed.
- //
- if (HandlerType != NULL) {
- PERF_FUNCTION_END ();
- WillReturn = TRUE;
- }
-
- ReturnStatus = EFI_SUCCESS;
- break;
-
- case EFI_WARN_INTERRUPT_SOURCE_QUIESCED:
- //
- // If at least one of the handlers returns EFI_WARN_INTERRUPT_SOURCE_QUIESCED
- // then the function will return EFI_SUCCESS.
- //
- ReturnStatus = EFI_SUCCESS;
- break;
-
- case EFI_WARN_INTERRUPT_SOURCE_PENDING:
- //
- // If all the handlers returned EFI_WARN_INTERRUPT_SOURCE_PENDING
- // then EFI_WARN_INTERRUPT_SOURCE_PENDING will be returned.
- //
- if (ReturnStatus != EFI_SUCCESS) {
- ReturnStatus = Status;
- }
-
- break;
-
- default:
- //
- // Unexpected status code returned.
- //
- ASSERT (FALSE);
- break;
- }
-
- if (WillReturn) {
- break;
- }
- }
-
- ASSERT (mSmiManageCallingDepth > 0);
- mSmiManageCallingDepth--;
-
- //
- // SmiHandlerUnRegister() calls from SMI handlers are deferred till this point.
- // Before returned from SmiManage, delete the SmiHandler which is
- // marked as ToRemove.
- // Note that SmiManage can be called recursively.
- //
- if (mSmiManageCallingDepth == 0) {
- //
- // Go through all SmiHandler in root SMI handlers
- //
- for ( Link = GetFirstNode (&mRootSmiEntry.SmiHandlers)
- ; !IsNull (&mRootSmiEntry.SmiHandlers, Link);
- )
- {
- //
- // SmiHandler might be removed in below, so cache the next link in Link
- //
- SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
- Link = GetNextNode (&mRootSmiEntry.SmiHandlers, Link);
- if (SmiHandler->ToRemove) {
- //
- // Remove SmiHandler if the ToRemove is set.
- //
- RemoveSmiHandler (SmiHandler, NULL);
- }
- }
-
- //
- // Go through all SmiHandler in non-root SMI handlers
- //
- for ( EntryLink = GetFirstNode (&mSmiEntryList)
- ; !IsNull (&mSmiEntryList, EntryLink);
- )
- {
- //
- // SmiEntry might be removed in below, so cache the next link in EntryLink
- //
- SmiEntry = CR (EntryLink, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
- EntryLink = GetNextNode (&mSmiEntryList, EntryLink);
- for ( Link = GetFirstNode (&SmiEntry->SmiHandlers)
- ; !IsNull (&SmiEntry->SmiHandlers, Link);
- )
- {
- //
- // SmiHandler might be removed in below, so cache the next link in Link
- //
- SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
- Link = GetNextNode (&SmiEntry->SmiHandlers, Link);
- if (SmiHandler->ToRemove) {
- if (RemoveSmiHandler (SmiHandler, SmiEntry)) {
- break;
- }
- }
- }
- }
- }
-
- PERF_FUNCTION_END ();
- return ReturnStatus;
-}
-
-/**
- Registers a handler to execute within SMM.
-
- @param Handler Handler service function pointer.
- @param HandlerType Points to the handler type or NULL for root SMI handlers.
- @param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.
-
- @retval EFI_SUCCESS Handler register success.
- @retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-SmiHandlerRegister (
- IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
- IN CONST EFI_GUID *HandlerType OPTIONAL,
- OUT EFI_HANDLE *DispatchHandle
- )
-{
- SMI_HANDLER *SmiHandler;
- SMI_ENTRY *SmiEntry;
- LIST_ENTRY *List;
-
- if ((Handler == NULL) || (DispatchHandle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- SmiHandler = AllocateZeroPool (sizeof (SMI_HANDLER));
- if (SmiHandler == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- SmiHandler->Signature = SMI_HANDLER_SIGNATURE;
- SmiHandler->Handler = Handler;
- SmiHandler->CallerAddr = (UINTN)RETURN_ADDRESS (0);
- SmiHandler->ToRemove = FALSE;
-
- if (HandlerType == NULL) {
- //
- // This is root SMI handler
- //
- SmiEntry = &mRootSmiEntry;
- } else {
- //
- // None root SMI handler
- //
- SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *)HandlerType, TRUE);
- if (SmiEntry == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
-
- List = &SmiEntry->SmiHandlers;
-
- SmiHandler->SmiEntry = SmiEntry;
- InsertTailList (List, &SmiHandler->Link);
-
- *DispatchHandle = (EFI_HANDLE)SmiHandler;
-
- return EFI_SUCCESS;
-}
-
-/**
- Unregister a handler in SMM.
-
- @param DispatchHandle The handle that was specified when the handler was registered.
-
- @retval EFI_SUCCESS Handler function was successfully unregistered.
- @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle.
-
-**/
-EFI_STATUS
-EFIAPI
-SmiHandlerUnRegister (
- IN EFI_HANDLE DispatchHandle
- )
-{
- SMI_HANDLER *SmiHandler;
- SMI_ENTRY *SmiEntry;
- LIST_ENTRY *EntryLink;
- LIST_ENTRY *HandlerLink;
-
- if (DispatchHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Look for it in root SMI handlers
- //
- SmiHandler = NULL;
- for ( HandlerLink = GetFirstNode (&mRootSmiEntry.SmiHandlers)
- ; !IsNull (&mRootSmiEntry.SmiHandlers, HandlerLink) && ((EFI_HANDLE)SmiHandler != DispatchHandle)
- ; HandlerLink = GetNextNode (&mRootSmiEntry.SmiHandlers, HandlerLink)
- )
- {
- SmiHandler = CR (HandlerLink, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
- }
-
- //
- // Look for it in non-root SMI handlers
- //
- for ( EntryLink = GetFirstNode (&mSmiEntryList)
- ; !IsNull (&mSmiEntryList, EntryLink) && ((EFI_HANDLE)SmiHandler != DispatchHandle)
- ; EntryLink = GetNextNode (&mSmiEntryList, EntryLink)
- )
- {
- SmiEntry = CR (EntryLink, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
- for ( HandlerLink = GetFirstNode (&SmiEntry->SmiHandlers)
- ; !IsNull (&SmiEntry->SmiHandlers, HandlerLink) && ((EFI_HANDLE)SmiHandler != DispatchHandle)
- ; HandlerLink = GetNextNode (&SmiEntry->SmiHandlers, HandlerLink)
- )
- {
- SmiHandler = CR (HandlerLink, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
- }
- }
-
- if (SmiHandler == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- ASSERT ((EFI_HANDLE)SmiHandler == DispatchHandle);
- SmiHandler->ToRemove = TRUE;
-
- if (mSmiManageCallingDepth > 0) {
- //
- // This function is called from SmiManage()
- // Do not delete or remove SmiHandler or SmiEntry now.
- // SmiManage will handle it later
- //
- return EFI_SUCCESS;
- }
-
- SmiEntry = SmiHandler->SmiEntry;
-
- //
- // For root SMI handler, use NULL for SmiEntry
- //
- RemoveSmiHandler (SmiHandler, (SmiEntry == &mRootSmiEntry) ? NULL : SmiEntry);
- return EFI_SUCCESS;
-}
+/** @file
+ SMI management.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PiSmmCore.h"
+
+//
+// mSmiManageCallingDepth is used to track the depth of recursive calls of SmiManage.
+//
+UINTN mSmiManageCallingDepth = 0;
+
+LIST_ENTRY mSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mSmiEntryList);
+
+SMI_ENTRY mRootSmiEntry = {
+ SMI_ENTRY_SIGNATURE,
+ INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntry.AllEntries),
+ { 0 },
+ INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntry.SmiHandlers),
+};
+
+/**
+ Finds the SMI entry for the requested handler type.
+
+ @param HandlerType The type of the interrupt
+ @param Create Create a new entry if not found
+
+ @return SMI entry
+
+**/
+SMI_ENTRY *
+EFIAPI
+SmmCoreFindSmiEntry (
+ IN EFI_GUID *HandlerType,
+ IN BOOLEAN Create
+ )
+{
+ LIST_ENTRY *Link;
+ SMI_ENTRY *Item;
+ SMI_ENTRY *SmiEntry;
+
+ //
+ // Search the SMI entry list for the matching GUID
+ //
+ SmiEntry = NULL;
+ for (Link = mSmiEntryList.ForwardLink;
+ Link != &mSmiEntryList;
+ Link = Link->ForwardLink)
+ {
+ Item = CR (Link, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
+ if (CompareGuid (&Item->HandlerType, HandlerType)) {
+ //
+ // This is the SMI entry
+ //
+ SmiEntry = Item;
+ break;
+ }
+ }
+
+ //
+ // If the protocol entry was not found and Create is TRUE, then
+ // allocate a new entry
+ //
+ if ((SmiEntry == NULL) && Create) {
+ SmiEntry = AllocatePool (sizeof (SMI_ENTRY));
+ if (SmiEntry != NULL) {
+ //
+ // Initialize new SMI entry structure
+ //
+ SmiEntry->Signature = SMI_ENTRY_SIGNATURE;
+ CopyGuid ((VOID *)&SmiEntry->HandlerType, HandlerType);
+ InitializeListHead (&SmiEntry->SmiHandlers);
+
+ //
+ // Add it to SMI entry list
+ //
+ InsertTailList (&mSmiEntryList, &SmiEntry->AllEntries);
+ }
+ }
+
+ return SmiEntry;
+}
+
+/**
+ Remove SmiHandler and free the memory it used.
+ If SmiEntry is empty, remove SmiEntry and free the memory it used.
+
+ @param SmiHandler Points to SMI handler.
+ @param SmiEntry Points to SMI Entry or NULL for root SMI handlers.
+
+ @retval TRUE SmiEntry is removed.
+ @retval FALSE SmiEntry is not removed.
+**/
+BOOLEAN
+RemoveSmiHandler (
+ IN SMI_HANDLER *SmiHandler,
+ IN SMI_ENTRY *SmiEntry
+ )
+{
+ ASSERT (SmiHandler->ToRemove);
+ RemoveEntryList (&SmiHandler->Link);
+ FreePool (SmiHandler);
+
+ //
+ // Remove the SMI_ENTRY if all handlers have been removed.
+ //
+ if (SmiEntry != NULL) {
+ if (IsListEmpty (&SmiEntry->SmiHandlers)) {
+ RemoveEntryList (&SmiEntry->AllEntries);
+ FreePool (SmiEntry);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Manage SMI of a particular type.
+
+ @param HandlerType Points to the handler type or NULL for root SMI handlers.
+ @param Context Points to an optional context buffer.
+ @param CommBuffer Points to the optional communication buffer.
+ @param CommBufferSize Points to the size of the optional communication buffer.
+
+ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was processed successfully but not quiesced.
+ @retval EFI_INTERRUPT_PENDING One or more SMI sources could not be quiesced.
+ @retval EFI_NOT_FOUND Interrupt source was not handled or quiesced.
+ @retval EFI_SUCCESS Interrupt source was handled and quiesced.
+
+**/
+EFI_STATUS
+EFIAPI
+SmiManage (
+ IN CONST EFI_GUID *HandlerType,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Head;
+ LIST_ENTRY *EntryLink;
+ SMI_ENTRY *SmiEntry;
+ SMI_HANDLER *SmiHandler;
+ EFI_STATUS ReturnStatus;
+ BOOLEAN WillReturn;
+ EFI_STATUS Status;
+
+ PERF_FUNCTION_BEGIN ();
+ mSmiManageCallingDepth++;
+ WillReturn = FALSE;
+ Status = EFI_NOT_FOUND;
+ ReturnStatus = Status;
+ if (HandlerType == NULL) {
+ //
+ // Root SMI handler
+ //
+ SmiEntry = &mRootSmiEntry;
+ } else {
+ //
+ // Non-root SMI handler
+ //
+ SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *)HandlerType, FALSE);
+ if (SmiEntry == NULL) {
+ //
+ // There is no handler registered for this interrupt source
+ //
+ PERF_FUNCTION_END ();
+ return Status;
+ }
+ }
+
+ Head = &SmiEntry->SmiHandlers;
+
+ for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
+ SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
+
+ Status = SmiHandler->Handler (
+ (EFI_HANDLE)SmiHandler,
+ Context,
+ CommBuffer,
+ CommBufferSize
+ );
+
+ switch (Status) {
+ case EFI_INTERRUPT_PENDING:
+ //
+ // If a handler returns EFI_INTERRUPT_PENDING and HandlerType is not NULL then
+ // no additional handlers will be processed and EFI_INTERRUPT_PENDING will be returned.
+ //
+ if (HandlerType != NULL) {
+ PERF_FUNCTION_END ();
+ ReturnStatus = EFI_INTERRUPT_PENDING;
+ WillReturn = TRUE;
+ } else {
+ //
+ // If any other handler's result sets ReturnStatus as EFI_SUCCESS, the return status
+ // will be EFI_SUCCESS.
+ //
+ if (ReturnStatus != EFI_SUCCESS) {
+ ReturnStatus = Status;
+ }
+ }
+
+ break;
+
+ case EFI_SUCCESS:
+ //
+ // If at least one of the handlers returns EFI_SUCCESS then the function will return
+ // EFI_SUCCESS. If a handler returns EFI_SUCCESS and HandlerType is not NULL then no
+ // additional handlers will be processed.
+ //
+ if (HandlerType != NULL) {
+ PERF_FUNCTION_END ();
+ WillReturn = TRUE;
+ }
+
+ ReturnStatus = EFI_SUCCESS;
+ break;
+
+ case EFI_WARN_INTERRUPT_SOURCE_QUIESCED:
+ //
+ // If at least one of the handlers returns EFI_WARN_INTERRUPT_SOURCE_QUIESCED
+ // then the function will return EFI_SUCCESS.
+ //
+ ReturnStatus = EFI_SUCCESS;
+ break;
+
+ case EFI_WARN_INTERRUPT_SOURCE_PENDING:
+ //
+ // If all the handlers returned EFI_WARN_INTERRUPT_SOURCE_PENDING
+ // then EFI_WARN_INTERRUPT_SOURCE_PENDING will be returned.
+ //
+ if (ReturnStatus != EFI_SUCCESS) {
+ ReturnStatus = Status;
+ }
+
+ break;
+
+ default:
+ //
+ // Unexpected status code returned.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+
+ if (WillReturn) {
+ break;
+ }
+ }
+
+ ASSERT (mSmiManageCallingDepth > 0);
+ mSmiManageCallingDepth--;
+
+ //
+ // SmiHandlerUnRegister() calls from SMI handlers are deferred till this point.
+ // Before returned from SmiManage, delete the SmiHandler which is
+ // marked as ToRemove.
+ // Note that SmiManage can be called recursively.
+ //
+ if (mSmiManageCallingDepth == 0) {
+ //
+ // Go through all SmiHandler in root SMI handlers
+ //
+ for ( Link = GetFirstNode (&mRootSmiEntry.SmiHandlers)
+ ; !IsNull (&mRootSmiEntry.SmiHandlers, Link);
+ )
+ {
+ //
+ // SmiHandler might be removed in below, so cache the next link in Link
+ //
+ SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
+ Link = GetNextNode (&mRootSmiEntry.SmiHandlers, Link);
+ if (SmiHandler->ToRemove) {
+ //
+ // Remove SmiHandler if the ToRemove is set.
+ //
+ RemoveSmiHandler (SmiHandler, NULL);
+ }
+ }
+
+ //
+ // Go through all SmiHandler in non-root SMI handlers
+ //
+ for ( EntryLink = GetFirstNode (&mSmiEntryList)
+ ; !IsNull (&mSmiEntryList, EntryLink);
+ )
+ {
+ //
+ // SmiEntry might be removed in below, so cache the next link in EntryLink
+ //
+ SmiEntry = CR (EntryLink, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
+ EntryLink = GetNextNode (&mSmiEntryList, EntryLink);
+ for ( Link = GetFirstNode (&SmiEntry->SmiHandlers)
+ ; !IsNull (&SmiEntry->SmiHandlers, Link);
+ )
+ {
+ //
+ // SmiHandler might be removed in below, so cache the next link in Link
+ //
+ SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
+ Link = GetNextNode (&SmiEntry->SmiHandlers, Link);
+ if (SmiHandler->ToRemove) {
+ if (RemoveSmiHandler (SmiHandler, SmiEntry)) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ PERF_FUNCTION_END ();
+ return ReturnStatus;
+}
+
+/**
+ Registers a handler to execute within SMM.
+
+ @param Handler Handler service function pointer.
+ @param HandlerType Points to the handler type or NULL for root SMI handlers.
+ @param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.
+
+ @retval EFI_SUCCESS Handler register success.
+ @retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmiHandlerRegister (
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
+ IN CONST EFI_GUID *HandlerType OPTIONAL,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ SMI_HANDLER *SmiHandler;
+ SMI_ENTRY *SmiEntry;
+ LIST_ENTRY *List;
+
+ if ((Handler == NULL) || (DispatchHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmiHandler = AllocateZeroPool (sizeof (SMI_HANDLER));
+ if (SmiHandler == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SmiHandler->Signature = SMI_HANDLER_SIGNATURE;
+ SmiHandler->Handler = Handler;
+ SmiHandler->CallerAddr = (UINTN)RETURN_ADDRESS (0);
+ SmiHandler->ToRemove = FALSE;
+
+ if (HandlerType == NULL) {
+ //
+ // This is root SMI handler
+ //
+ SmiEntry = &mRootSmiEntry;
+ } else {
+ //
+ // None root SMI handler
+ //
+ SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *)HandlerType, TRUE);
+ if (SmiEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ List = &SmiEntry->SmiHandlers;
+
+ SmiHandler->SmiEntry = SmiEntry;
+ InsertTailList (List, &SmiHandler->Link);
+
+ *DispatchHandle = (EFI_HANDLE)SmiHandler;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregister a handler in SMM.
+
+ @param DispatchHandle The handle that was specified when the handler was registered.
+
+ @retval EFI_SUCCESS Handler function was successfully unregistered.
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle.
+
+**/
+EFI_STATUS
+EFIAPI
+SmiHandlerUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ SMI_HANDLER *SmiHandler;
+ SMI_ENTRY *SmiEntry;
+ LIST_ENTRY *EntryLink;
+ LIST_ENTRY *HandlerLink;
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Look for it in root SMI handlers
+ //
+ SmiHandler = NULL;
+ for ( HandlerLink = GetFirstNode (&mRootSmiEntry.SmiHandlers)
+ ; !IsNull (&mRootSmiEntry.SmiHandlers, HandlerLink) && ((EFI_HANDLE)SmiHandler != DispatchHandle)
+ ; HandlerLink = GetNextNode (&mRootSmiEntry.SmiHandlers, HandlerLink)
+ )
+ {
+ SmiHandler = CR (HandlerLink, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
+ }
+
+ //
+ // Look for it in non-root SMI handlers
+ //
+ for ( EntryLink = GetFirstNode (&mSmiEntryList)
+ ; !IsNull (&mSmiEntryList, EntryLink) && ((EFI_HANDLE)SmiHandler != DispatchHandle)
+ ; EntryLink = GetNextNode (&mSmiEntryList, EntryLink)
+ )
+ {
+ SmiEntry = CR (EntryLink, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
+ for ( HandlerLink = GetFirstNode (&SmiEntry->SmiHandlers)
+ ; !IsNull (&SmiEntry->SmiHandlers, HandlerLink) && ((EFI_HANDLE)SmiHandler != DispatchHandle)
+ ; HandlerLink = GetNextNode (&SmiEntry->SmiHandlers, HandlerLink)
+ )
+ {
+ SmiHandler = CR (HandlerLink, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
+ }
+ }
+
+ if (SmiHandler == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT ((EFI_HANDLE)SmiHandler == DispatchHandle);
+ SmiHandler->ToRemove = TRUE;
+
+ if (mSmiManageCallingDepth > 0) {
+ //
+ // This function is called from SmiManage()
+ // Do not delete or remove SmiHandler or SmiEntry now.
+ // SmiManage will handle it later
+ //
+ return EFI_SUCCESS;
+ }
+
+ SmiEntry = SmiHandler->SmiEntry;
+
+ //
+ // For root SMI handler, use NULL for SmiEntry
+ //
+ RemoveSmiHandler (SmiHandler, (SmiEntry == &mRootSmiEntry) ? NULL : SmiEntry);
+ return EFI_SUCCESS;
+}