]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Hand/Notify.c
Check in DxeCore for Nt32 platform. Currently, it does not follow PI/UEFI2.1.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Notify.c
diff --git a/MdeModulePkg/Core/Dxe/Hand/Notify.c b/MdeModulePkg/Core/Dxe/Hand/Notify.c
new file mode 100644 (file)
index 0000000..f48fee7
--- /dev/null
@@ -0,0 +1,333 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this 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
+Module Name:\r
+\r
+  notify.c\r
+\r
+Abstract:\r
+\r
+  EFI notify infrastructure\r
+\r
+\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include <DxeMain.h>\r
+\r
+VOID\r
+CoreNotifyProtocolEntry (\r
+  IN PROTOCOL_ENTRY   *ProtEntry\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Signal event for every protocol in protocol entry.\r
+\r
+Arguments:\r
+\r
+  ProtEntry     - Protocol entry\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  PROTOCOL_NOTIFY     *ProtNotify;\r
+  LIST_ENTRY          *Link;\r
+\r
+  ASSERT_LOCKED (&gProtocolDatabaseLock);\r
+\r
+  for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {\r
+    ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
+    CoreSignalEvent (ProtNotify->Event);\r
+  }\r
+}\r
+\r
+\r
+PROTOCOL_INTERFACE *\r
+CoreRemoveInterfaceFromProtocol (\r
+  IN IHANDLE        *Handle,\r
+  IN EFI_GUID       *Protocol,\r
+  IN VOID           *Interface\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Removes Protocol from the protocol list (but not the handle list).\r
+\r
+Arguments:\r
+\r
+  Handle -  The handle to remove protocol on.\r
+\r
+  Protocol  -  GUID of the protocol to be moved\r
+\r
+  Interface - The interface of the protocol\r
+\r
+Returns:\r
+\r
+  Protocol Entry\r
+\r
+--*/\r
+{\r
+  PROTOCOL_INTERFACE  *Prot;\r
+  PROTOCOL_NOTIFY     *ProtNotify;\r
+  PROTOCOL_ENTRY      *ProtEntry;\r
+  LIST_ENTRY          *Link;\r
+\r
+  ASSERT_LOCKED (&gProtocolDatabaseLock);\r
+\r
+  Prot = CoreFindProtocolInterface (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
+\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
+\r
+    RemoveEntryList (&Prot->ByProtocol);\r
+  }\r
+\r
+  return Prot;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CoreRegisterProtocolNotify (\r
+  IN EFI_GUID       *Protocol,\r
+  IN EFI_EVENT      Event,\r
+  OUT  VOID           **Registration\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add a new protocol notification record for the request protocol.\r
+\r
+Arguments:\r
+\r
+  Protocol      - The requested protocol to add the notify registration\r
+\r
+  Event         - The event to signal \r
+\r
+  Registration  - Returns the registration record\r
+\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER       - Invalid parameter\r
+\r
+  EFI_SUCCESS                 - Successfully returned the registration record that has been added\r
+  \r
+--*/\r
+{\r
+  PROTOCOL_ENTRY      *ProtEntry;\r
+  PROTOCOL_NOTIFY     *ProtNotify;\r
+  EFI_STATUS        Status;\r
+  \r
+  if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL))  {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CoreAcquireProtocolLock ();\r
+\r
+  ProtNotify = NULL;\r
+  \r
+  //\r
+  // Get the protocol entry to add the notification too\r
+  //\r
+\r
+  ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);\r
+  if (ProtEntry != NULL) {\r
+\r
+    //\r
+    // Allocate a new notification record\r
+    //\r
+\r
+    ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY));\r
+\r
+    if (ProtNotify != NULL) {\r
+      \r
+      ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;\r
+      ProtNotify->Protocol = ProtEntry;\r
+      ProtNotify->Event = Event;\r
+      //\r
+      // start at the begining\r
+      //\r
+      ProtNotify->Position = &ProtEntry->Protocols; \r
+\r
+      InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);\r
+    }\r
+  }\r
+\r
+  CoreReleaseProtocolLock ();\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
+\r
+  Status = EFI_OUT_OF_RESOURCES;\r
+  if (ProtNotify != NULL) {\r
+    *Registration = ProtNotify;\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CoreReinstallProtocolInterface (\r
+  IN EFI_HANDLE     UserHandle,\r
+  IN EFI_GUID       *Protocol,\r
+  IN VOID           *OldInterface,\r
+  IN VOID           *NewInterface\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Reinstall a protocol interface on a device handle.  The OldInterface for Protocol is replaced by the NewInterface.\r
+\r
+Arguments:\r
+\r
+  UserHandle    - Handle on which the interface is to be reinstalled\r
+  Protocol      - The numeric ID of the interface\r
+  OldInterface  - A pointer to the old interface\r
+  NewInterface  - A pointer to the new interface \r
+\r
+\r
+Returns:\r
+\r
+  Status code.\r
+\r
+  On EFI_SUCCESS            The protocol interface was installed\r
+  On EFI_NOT_FOUND          The OldInterface on the handle was not found\r
+  On EFI_INVALID_PARAMETER  One of the parameters has an invalid value\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  IHANDLE                   *Handle;\r
+  PROTOCOL_INTERFACE        *Prot;\r
+  PROTOCOL_ENTRY            *ProtEntry;\r
+\r
+  Status = CoreValidateHandle (UserHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Protocol == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Handle = (IHANDLE *) UserHandle;\r
+\r
+  //\r
+  // Lock the protocol database\r
+  //\r
+  CoreAcquireProtocolLock ();\r
+\r
+  //\r
+  // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
+  //\r
+  Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);\r
+  if (Prot == NULL) {\r
+    CoreReleaseProtocolLock ();\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled\r
+  //\r
+  Status = CoreDisconnectControllersUsingProtocolInterface (\r
+             UserHandle,\r
+             Prot\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // One or more drivers refused to release, so return the error\r
+    //\r
+    CoreReleaseProtocolLock ();\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Remove the protocol interface from the protocol\r
+  //\r
+  Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);\r
+\r
+  if (Prot == NULL) {\r
+    CoreReleaseProtocolLock ();\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  ProtEntry = Prot->Protocol;\r
+\r
+  //\r
+  // Update the interface on the protocol\r
+  //\r
+  Prot->Interface = NewInterface;\r
+\r
+  //\r
+  // Add this protocol interface to the tail of the\r
+  // protocol entry\r
+  //\r
+  InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
+\r
+  //\r
+  // Update the Key to show that the handle has been created/modified\r
+  //\r
+  gHandleDatabaseKey++;\r
+  Handle->Key = gHandleDatabaseKey;\r
+\r
+  //\r
+  // Release the lock and connect all drivers to UserHandle\r
+  //\r
+  CoreReleaseProtocolLock ();\r
+  Status = CoreConnectController (\r
+                  UserHandle, \r
+                  NULL, \r
+                  NULL, \r
+                  TRUE\r
+                  );\r
+  CoreAcquireProtocolLock ();\r
+  \r
+  //\r
+  // Notify the notification list for this protocol\r
+  //\r
+  CoreNotifyProtocolEntry (ProtEntry);\r
+\r
+  CoreReleaseProtocolLock ();\r
+  \r
+  return EFI_SUCCESS;\r
+}\r