]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StandaloneMmPkg/Core/Notify.c
StandaloneMmPkg/Core: Implementation of Standalone MM Core Module.
[mirror_edk2.git] / StandaloneMmPkg / Core / Notify.c
diff --git a/StandaloneMmPkg/Core/Notify.c b/StandaloneMmPkg/Core/Notify.c
new file mode 100644 (file)
index 0000000..57a03fe
--- /dev/null
@@ -0,0 +1,203 @@
+/** @file\r
+  Support functions for UEFI protocol notification infrastructure.\r
+\r
+  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "StandaloneMmCore.h"\r
+\r
+/**\r
+  Signal event for every protocol in protocol entry.\r
+\r
+  @param  Prot                   Protocol interface\r
+\r
+**/\r
+VOID\r
+MmNotifyProtocol (\r
+  IN PROTOCOL_INTERFACE  *Prot\r
+  )\r
+{\r
+  PROTOCOL_ENTRY   *ProtEntry;\r
+  PROTOCOL_NOTIFY  *ProtNotify;\r
+  LIST_ENTRY       *Link;\r
+\r
+  ProtEntry = Prot->Protocol;\r
+  for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {\r
+    ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
+    ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);\r
+  }\r
+}\r
+\r
+/**\r
+  Removes Protocol from the protocol list (but not the handle list).\r
+\r
+  @param  Handle                 The handle to remove protocol on.\r
+  @param  Protocol               GUID of the protocol to be moved\r
+  @param  Interface              The interface of the protocol\r
+\r
+  @return Protocol Entry\r
+\r
+**/\r
+PROTOCOL_INTERFACE *\r
+MmRemoveInterfaceFromProtocol (\r
+  IN IHANDLE   *Handle,\r
+  IN EFI_GUID  *Protocol,\r
+  IN VOID      *Interface\r
+  )\r
+{\r
+  PROTOCOL_INTERFACE  *Prot;\r
+  PROTOCOL_NOTIFY     *ProtNotify;\r
+  PROTOCOL_ENTRY      *ProtEntry;\r
+  LIST_ENTRY          *Link;\r
+\r
+  Prot = MmFindProtocolInterface (Handle, Protocol, Interface);\r
+  if (Prot != NULL) {\r
+\r
+    ProtEntry = Prot->Protocol;\r
+\r
+    //\r
+    // If there's a protocol notify location pointing to this entry, back it up one\r
+    //\r
+    for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {\r
+      ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
+\r
+      if (ProtNotify->Position == &Prot->ByProtocol) {\r
+        ProtNotify->Position = Prot->ByProtocol.BackLink;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Remove the protocol interface entry\r
+    //\r
+    RemoveEntryList (&Prot->ByProtocol);\r
+  }\r
+\r
+  return Prot;\r
+}\r
+\r
+/**\r
+  Add a new protocol notification record for the request protocol.\r
+\r
+  @param  Protocol               The requested protocol to add the notify\r
+                                 registration\r
+  @param  Function               Points to the notification function\r
+  @param  Registration           Returns the registration record\r
+\r
+  @retval EFI_SUCCESS            Successfully returned the registration record\r
+                                 that has been added or unhooked\r
+  @retval EFI_INVALID_PARAMETER  Protocol is NULL or Registration is NULL\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory resource to finish the request\r
+  @retval EFI_NOT_FOUND          If the registration is not found when Function == NULL\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmRegisterProtocolNotify (\r
+  IN  CONST EFI_GUID     *Protocol,\r
+  IN  EFI_MM_NOTIFY_FN  Function,\r
+  OUT VOID               **Registration\r
+  )\r
+{\r
+  PROTOCOL_ENTRY   *ProtEntry;\r
+  PROTOCOL_NOTIFY  *ProtNotify;\r
+  LIST_ENTRY       *Link;\r
+  EFI_STATUS       Status;\r
+\r
+  if (Protocol == NULL || Registration == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Function == NULL) {\r
+    //\r
+    // Get the protocol entry per Protocol\r
+    //\r
+    ProtEntry = MmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE);\r
+    if (ProtEntry != NULL) {\r
+      ProtNotify = (PROTOCOL_NOTIFY * )*Registration;\r
+      for (Link = ProtEntry->Notify.ForwardLink;\r
+           Link != &ProtEntry->Notify;\r
+           Link = Link->ForwardLink) {\r
+        //\r
+        // Compare the notification record\r
+        //\r
+        if (ProtNotify == (CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))) {\r
+          //\r
+          // If Registration is an existing registration, then unhook it\r
+          //\r
+          ProtNotify->Signature = 0;\r
+          RemoveEntryList (&ProtNotify->Link);\r
+          FreePool (ProtNotify);\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+    //\r
+    // If the registration is not found\r
+    //\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  ProtNotify = NULL;\r
+\r
+  //\r
+  // Get the protocol entry to add the notification too\r
+  //\r
+  ProtEntry = MmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);\r
+  if (ProtEntry != NULL) {\r
+    //\r
+    // Find whether notification already exist\r
+    //\r
+    for (Link = ProtEntry->Notify.ForwardLink;\r
+         Link != &ProtEntry->Notify;\r
+         Link = Link->ForwardLink) {\r
+\r
+      ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
+      if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&\r
+          (ProtNotify->Function == Function)) {\r
+\r
+        //\r
+        // Notification already exist\r
+        //\r
+        *Registration = ProtNotify;\r
+\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Allocate a new notification record\r
+    //\r
+    ProtNotify = AllocatePool (sizeof (PROTOCOL_NOTIFY));\r
+    if (ProtNotify != NULL) {\r
+      ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;\r
+      ProtNotify->Protocol = ProtEntry;\r
+      ProtNotify->Function = Function;\r
+      //\r
+      // Start at the ending\r
+      //\r
+      ProtNotify->Position = ProtEntry->Protocols.BackLink;\r
+\r
+      InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Done.  If we have a protocol notify entry, then return it.\r
+  // Otherwise, we must have run out of resources trying to add one\r
+  //\r
+  Status = EFI_OUT_OF_RESOURCES;\r
+  if (ProtNotify != NULL) {\r
+    *Registration = ProtNotify;\r
+    Status = EFI_SUCCESS;\r
+  }\r
+  return Status;\r
+}\r