• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Support functions for UEFI protocol notification infrastructure.
3 
4   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials are licensed and made available
6   under the terms and conditions of the BSD License which accompanies this
7   distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "PiSmmCore.h"
16 
17 /**
18   Signal event for every protocol in protocol entry.
19 
20   @param  Prot                   Protocol interface
21 
22 **/
23 VOID
SmmNotifyProtocol(IN PROTOCOL_INTERFACE * Prot)24 SmmNotifyProtocol (
25   IN PROTOCOL_INTERFACE  *Prot
26   )
27 {
28   PROTOCOL_ENTRY   *ProtEntry;
29   PROTOCOL_NOTIFY  *ProtNotify;
30   LIST_ENTRY       *Link;
31 
32   ProtEntry = Prot->Protocol;
33   for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
34     ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
35     ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);
36   }
37 }
38 
39 /**
40   Removes Protocol from the protocol list (but not the handle list).
41 
42   @param  Handle                 The handle to remove protocol on.
43   @param  Protocol               GUID of the protocol to be moved
44   @param  Interface              The interface of the protocol
45 
46   @return Protocol Entry
47 
48 **/
49 PROTOCOL_INTERFACE *
SmmRemoveInterfaceFromProtocol(IN IHANDLE * Handle,IN EFI_GUID * Protocol,IN VOID * Interface)50 SmmRemoveInterfaceFromProtocol (
51   IN IHANDLE   *Handle,
52   IN EFI_GUID  *Protocol,
53   IN VOID      *Interface
54   )
55 {
56   PROTOCOL_INTERFACE  *Prot;
57   PROTOCOL_NOTIFY     *ProtNotify;
58   PROTOCOL_ENTRY      *ProtEntry;
59   LIST_ENTRY          *Link;
60 
61   Prot = SmmFindProtocolInterface (Handle, Protocol, Interface);
62   if (Prot != NULL) {
63 
64     ProtEntry = Prot->Protocol;
65 
66     //
67     // If there's a protocol notify location pointing to this entry, back it up one
68     //
69     for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
70       ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
71 
72       if (ProtNotify->Position == &Prot->ByProtocol) {
73         ProtNotify->Position = Prot->ByProtocol.BackLink;
74       }
75     }
76 
77     //
78     // Remove the protocol interface entry
79     //
80     RemoveEntryList (&Prot->ByProtocol);
81   }
82 
83   return Prot;
84 }
85 
86 /**
87   Add a new protocol notification record for the request protocol.
88 
89   @param  Protocol               The requested protocol to add the notify
90                                  registration
91   @param  Function               Points to the notification function
92   @param  Registration           Returns the registration record
93 
94   @retval EFI_SUCCESS            Successfully returned the registration record
95                                  that has been added or unhooked
96   @retval EFI_INVALID_PARAMETER  Protocol is NULL or Registration is NULL
97   @retval EFI_OUT_OF_RESOURCES   Not enough memory resource to finish the request
98   @retval EFI_NOT_FOUND          If the registration is not found when Function == NULL
99 
100 **/
101 EFI_STATUS
102 EFIAPI
SmmRegisterProtocolNotify(IN CONST EFI_GUID * Protocol,IN EFI_SMM_NOTIFY_FN Function,OUT VOID ** Registration)103 SmmRegisterProtocolNotify (
104   IN  CONST EFI_GUID     *Protocol,
105   IN  EFI_SMM_NOTIFY_FN  Function,
106   OUT VOID               **Registration
107   )
108 {
109   PROTOCOL_ENTRY   *ProtEntry;
110   PROTOCOL_NOTIFY  *ProtNotify;
111   LIST_ENTRY       *Link;
112   EFI_STATUS       Status;
113 
114   if (Protocol == NULL || Registration == NULL) {
115     return EFI_INVALID_PARAMETER;
116   }
117 
118   if (Function == NULL) {
119   	//
120     // Get the protocol entry per Protocol
121     //
122     ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE);
123     if (ProtEntry != NULL) {
124       ProtNotify = (PROTOCOL_NOTIFY * )*Registration;
125       for (Link = ProtEntry->Notify.ForwardLink;
126            Link != &ProtEntry->Notify;
127            Link = Link->ForwardLink) {
128         //
129         // Compare the notification record
130         //
131         if (ProtNotify == (CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))){
132           //
133           // If Registration is an existing registration, then unhook it
134           //
135           ProtNotify->Signature = 0;
136           RemoveEntryList (&ProtNotify->Link);
137           FreePool (ProtNotify);
138           return EFI_SUCCESS;
139         }
140       }
141     }
142     //
143     // If the registration is not found
144     //
145     return EFI_NOT_FOUND;
146   }
147 
148   ProtNotify = NULL;
149 
150   //
151   // Get the protocol entry to add the notification too
152   //
153   ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);
154   if (ProtEntry != NULL) {
155     //
156     // Find whether notification already exist
157     //
158     for (Link = ProtEntry->Notify.ForwardLink;
159          Link != &ProtEntry->Notify;
160          Link = Link->ForwardLink) {
161 
162       ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
163       if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&
164           (ProtNotify->Function == Function)) {
165 
166         //
167         // Notification already exist
168         //
169         *Registration = ProtNotify;
170 
171         return EFI_SUCCESS;
172       }
173     }
174 
175     //
176     // Allocate a new notification record
177     //
178     ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));
179     if (ProtNotify != NULL) {
180       ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
181       ProtNotify->Protocol = ProtEntry;
182       ProtNotify->Function = Function;
183       //
184       // Start at the ending
185       //
186       ProtNotify->Position = ProtEntry->Protocols.BackLink;
187 
188       InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
189     }
190   }
191 
192   //
193   // Done.  If we have a protocol notify entry, then return it.
194   // Otherwise, we must have run out of resources trying to add one
195   //
196   Status = EFI_OUT_OF_RESOURCES;
197   if (ProtNotify != NULL) {
198     *Registration = ProtNotify;
199     Status = EFI_SUCCESS;
200   }
201   return Status;
202 }
203