PI 1.4 clarified SMM register protocol notify function return status as below:
EFI_SUCCESS           Successfully returned the registration record that has
                      been added or unhooked
EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL
The implementation of SmmRegisterProtocolNotify() already followed this new
rule, needn't to be updated.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17349 6f19259b-4bc3-4df7-8a09-765794883524
		
	
		
			
				
	
	
		
			203 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Support functions for UEFI protocol notification infrastructure.
 | |
| 
 | |
|   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
 | |
|   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.             
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "PiSmmCore.h"
 | |
| 
 | |
| /**
 | |
|   Signal event for every protocol in protocol entry.
 | |
| 
 | |
|   @param  Prot                   Protocol interface
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SmmNotifyProtocol (
 | |
|   IN PROTOCOL_INTERFACE  *Prot
 | |
|   )
 | |
| {
 | |
|   PROTOCOL_ENTRY   *ProtEntry;
 | |
|   PROTOCOL_NOTIFY  *ProtNotify;
 | |
|   LIST_ENTRY       *Link;
 | |
| 
 | |
|   ProtEntry = Prot->Protocol;
 | |
|   for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
 | |
|     ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
 | |
|     ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Removes Protocol from the protocol list (but not the handle list).
 | |
| 
 | |
|   @param  Handle                 The handle to remove protocol on.
 | |
|   @param  Protocol               GUID of the protocol to be moved
 | |
|   @param  Interface              The interface of the protocol
 | |
| 
 | |
|   @return Protocol Entry
 | |
| 
 | |
| **/
 | |
| PROTOCOL_INTERFACE *
 | |
| SmmRemoveInterfaceFromProtocol (
 | |
|   IN IHANDLE   *Handle,
 | |
|   IN EFI_GUID  *Protocol,
 | |
|   IN VOID      *Interface
 | |
|   )
 | |
| {
 | |
|   PROTOCOL_INTERFACE  *Prot;
 | |
|   PROTOCOL_NOTIFY     *ProtNotify;
 | |
|   PROTOCOL_ENTRY      *ProtEntry;
 | |
|   LIST_ENTRY          *Link;
 | |
| 
 | |
|   Prot = SmmFindProtocolInterface (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;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Add a new protocol notification record for the request protocol.
 | |
| 
 | |
|   @param  Protocol               The requested protocol to add the notify
 | |
|                                  registration
 | |
|   @param  Function               Points to the notification function
 | |
|   @param  Registration           Returns the registration record
 | |
| 
 | |
|   @retval EFI_SUCCESS            Successfully returned the registration record
 | |
|                                  that has been added or unhooked
 | |
|   @retval EFI_INVALID_PARAMETER  Protocol is NULL or Registration is NULL
 | |
|   @retval EFI_OUT_OF_RESOURCES   Not enough memory resource to finish the request
 | |
|   @retval EFI_NOT_FOUND          If the registration is not found when Function == NULL
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmRegisterProtocolNotify (
 | |
|   IN  CONST EFI_GUID     *Protocol,
 | |
|   IN  EFI_SMM_NOTIFY_FN  Function,
 | |
|   OUT VOID               **Registration
 | |
|   )
 | |
| {
 | |
|   PROTOCOL_ENTRY   *ProtEntry;
 | |
|   PROTOCOL_NOTIFY  *ProtNotify;
 | |
|   LIST_ENTRY       *Link;
 | |
|   EFI_STATUS       Status;
 | |
| 
 | |
|   if (Protocol == NULL || Registration == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Function == NULL) {
 | |
|   	//
 | |
|     // Get the protocol entry per Protocol
 | |
|     //
 | |
|     ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE);
 | |
|     if (ProtEntry != NULL) {
 | |
|       ProtNotify = (PROTOCOL_NOTIFY * )*Registration;
 | |
|       for (Link = ProtEntry->Notify.ForwardLink;
 | |
|            Link != &ProtEntry->Notify;
 | |
|            Link = Link->ForwardLink) {
 | |
|         //
 | |
|         // Compare the notification record 
 | |
|         //
 | |
|         if (ProtNotify == (CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))){
 | |
|           //
 | |
|           // If Registration is an existing registration, then unhook it
 | |
|           //
 | |
|           ProtNotify->Signature = 0;
 | |
|           RemoveEntryList (&ProtNotify->Link);
 | |
|           FreePool (ProtNotify);
 | |
|           return EFI_SUCCESS;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // If the registration is not found
 | |
|     //
 | |
|     return EFI_NOT_FOUND;
 | |
|   } 
 | |
| 
 | |
|   ProtNotify = NULL;
 | |
| 
 | |
|   //
 | |
|   // Get the protocol entry to add the notification too
 | |
|   //
 | |
|   ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);
 | |
|   if (ProtEntry != NULL) {
 | |
|     //
 | |
|     // Find whether notification already exist
 | |
|     //
 | |
|     for (Link = ProtEntry->Notify.ForwardLink;
 | |
|          Link != &ProtEntry->Notify;
 | |
|          Link = Link->ForwardLink) {
 | |
| 
 | |
|       ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
 | |
|       if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&
 | |
|           (ProtNotify->Function == Function)) {
 | |
| 
 | |
|         //
 | |
|         // Notification already exist
 | |
|         //
 | |
|         *Registration = ProtNotify;
 | |
| 
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Allocate a new notification record
 | |
|     //
 | |
|     ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));
 | |
|     if (ProtNotify != NULL) {
 | |
|       ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
 | |
|       ProtNotify->Protocol = ProtEntry;
 | |
|       ProtNotify->Function = Function;
 | |
|       //
 | |
|       // Start at the ending
 | |
|       //
 | |
|       ProtNotify->Position = ProtEntry->Protocols.BackLink;
 | |
| 
 | |
|       InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 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;
 | |
| }
 |