From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Core/CORE_DXE/Notify.c | 344 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 Core/CORE_DXE/Notify.c (limited to 'Core/CORE_DXE/Notify.c') diff --git a/Core/CORE_DXE/Notify.c b/Core/CORE_DXE/Notify.c new file mode 100644 index 0000000..ea8e0fd --- /dev/null +++ b/Core/CORE_DXE/Notify.c @@ -0,0 +1,344 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + notify.c + +Abstract: + + EFI notify infrastructure + + + +Revision History + +--*/ + +#include "hand.h" + + + +VOID +CoreNotifyProtocolEntry ( + IN PROTOCOL_ENTRY *ProtEntry + ) +/*++ + +Routine Description: + + Signal event for every protocol in protocol entry. + +Arguments: + + ProtEntry - Protocol entry + +Returns: + +--*/ +{ + PROTOCOL_NOTIFY *ProtNotify; + EFI_LIST_ENTRY *Link; + + ASSERT_LOCKED (&gProtocolDatabaseLock); +//*** AMI PORTING BEGIN ***// +//Bug fix: +// CoreSignalEvent may lead to immediate call of the event notification function, +// which may call CloseEvent, which invalidates current ProtNotify. +// As a result, Link=Link->ForwardLink after the loop body ends up +// with an invalid pointer (Link is part of the invalid ProtNotify). +// The code is updated to get pointer to the next element before CoreSignalEvent. +// for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify;) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + Link=Link->ForwardLink; +//*** AMI PORTING END *****// + CoreSignalEvent (ProtNotify->Event); + } +} + + +PROTOCOL_INTERFACE * +CoreRemoveInterfaceFromProtocol ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Removes Protocol from the protocol list (but not the handle list). + +Arguments: + + Handle - The handle to remove protocol on. + + Protocol - GUID of the protocol to be moved + + Interface - The interface of the protocol + +Returns: + + Protocol Entry + +--*/ +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_NOTIFY *ProtNotify; + PROTOCOL_ENTRY *ProtEntry; + EFI_LIST_ENTRY *Link; + + ASSERT_LOCKED (&gProtocolDatabaseLock); + + Prot = CoreFindProtocolInterface (Handle, Protocol, Interface); + if (Prot != NULL) { + + ProtEntry = Prot->Protocol; + + // + // If there's a protocol notify location pointing to this entry, back it up one + // + + for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + + if (ProtNotify->Position == &Prot->ByProtocol) { + ProtNotify->Position = Prot->ByProtocol.BackLink; + } + } + + // + // Remove the protocol interface entry + // + + RemoveEntryList (&Prot->ByProtocol); + } + + return Prot; +} + + +EFI_BOOTSERVICE +EFI_STATUS +EFIAPI +CoreRegisterProtocolNotify ( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ) +/*++ + +Routine Description: + + Add a new protocol notification record for the request protocol. + +Arguments: + + Protocol - The requested protocol to add the notify registration + + Event - The event to signal + + Registration - Returns the registration record + + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_SUCCESS - Successfully returned the registration record that has been added + +--*/ +{ + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_NOTIFY *ProtNotify; + EFI_STATUS Status; + + if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireProtocolLock (); + + ProtNotify = NULL; + + // + // Get the protocol entry to add the notification too + // + + ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); + if (ProtEntry != NULL) { + + // + // Allocate a new notification record + // + + ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY)); + + if (ProtNotify != NULL) { + + ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; + ProtNotify->Protocol = ProtEntry; + ProtNotify->Event = Event; + // + // start at the begining + // + ProtNotify->Position = &ProtEntry->Protocols; + + InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); + } + } + + CoreReleaseProtocolLock (); + + // + // Done. If we have a protocol notify entry, then return it. + // Otherwise, we must have run out of resources trying to add one + // + + Status = EFI_OUT_OF_RESOURCES; + if (ProtNotify != NULL) { + *Registration = ProtNotify; + Status = EFI_SUCCESS; + } + + return Status; +} + + +EFI_BOOTSERVICE +EFI_STATUS +EFIAPI +CoreReinstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ) +/*++ + +Routine Description: + + Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. + +Arguments: + + UserHandle - Handle on which the interface is to be reinstalled + Protocol - The numeric ID of the interface + OldInterface - A pointer to the old interface + NewInterface - A pointer to the new interface + + +Returns: + + Status code. + + On EFI_SUCCESS The protocol interface was installed + On EFI_NOT_FOUND The OldInterface on the handle was not found + On EFI_INVALID_PARAMETER One of the parameters has an invalid value + +--*/ +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + Handle = (IHANDLE *) UserHandle; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Check that Protocol exists on UserHandle, and Interface matches the interface in the database + // + Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface); + if (Prot == NULL) { + CoreReleaseProtocolLock (); + return EFI_NOT_FOUND; + } + + // + // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled + // + Status = CoreDisconnectControllersUsingProtocolInterface ( + UserHandle, + Prot + ); + if (EFI_ERROR (Status)) { + // + // One or more drivers refused to release, so return the error + // + CoreReleaseProtocolLock (); + return Status; + } + + // + // Remove the protocol interface from the protocol + // + Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface); + + if (Prot == NULL) { + CoreReleaseProtocolLock (); + return EFI_NOT_FOUND; + } + + ProtEntry = Prot->Protocol; + + // + // Update the interface on the protocol + // + Prot->Interface = NewInterface; + + // + // Add this protocol interface to the tail of the + // protocol entry + // + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); + + // + // Update the Key to show that the handle has been created/modified + // + gHandleDatabaseKey++; + Handle->Key = gHandleDatabaseKey; + + // + // Release the lock and connect all drivers to UserHandle + // + CoreReleaseProtocolLock (); + Status = CoreConnectController ( + UserHandle, + NULL, + NULL, + TRUE + ); + CoreAcquireProtocolLock (); + + // + // Notify the notification list for this protocol + // + CoreNotifyProtocolEntry (ProtEntry); + + CoreReleaseProtocolLock (); + + return EFI_SUCCESS; +} -- cgit v1.2.3