1 /*++
2 
3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   Event.c
15 
16 Abstract:
17 
18   Support for Event lib fucntions.
19 
20 --*/
21 
22 #include "Tiano.h"
23 #include "EfiDriverLib.h"
24 
25 EFI_EVENT
EfiLibCreateProtocolNotifyEvent(IN EFI_GUID * ProtocolGuid,IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,IN VOID * NotifyContext,OUT VOID ** Registration)26 EfiLibCreateProtocolNotifyEvent (
27   IN EFI_GUID             *ProtocolGuid,
28   IN EFI_TPL              NotifyTpl,
29   IN EFI_EVENT_NOTIFY     NotifyFunction,
30   IN VOID                 *NotifyContext,
31   OUT VOID                **Registration
32   )
33 /*++
34 
35 Routine Description:
36 
37   Create a protocol notification event and return it.
38 
39 Arguments:
40 
41   ProtocolGuid    - Protocol to register notification event on.
42 
43   NotifyTpl       - Maximum TPL to single the NotifyFunction.
44 
45   NotifyFunction  - EFI notification routine.
46 
47   NotifyContext   - Context passed into Event when it is created.
48 
49   Registration    - Registration key returned from RegisterProtocolNotify().
50 
51 Returns:
52 
53   The EFI_EVENT that has been registered to be signaled when a ProtocolGuid
54   is added to the system.
55 
56 --*/
57 {
58   EFI_STATUS  Status;
59   EFI_EVENT   Event;
60 
61   //
62   // Create the event
63   //
64 
65   Status = gBS->CreateEvent (
66                   EFI_EVENT_NOTIFY_SIGNAL,
67                   NotifyTpl,
68                   NotifyFunction,
69                   NotifyContext,
70                   &Event
71                   );
72   ASSERT (!EFI_ERROR (Status));
73 
74   //
75   // Register for protocol notifactions on this event
76   //
77 
78   Status = gBS->RegisterProtocolNotify (
79                   ProtocolGuid,
80                   Event,
81                   Registration
82                   );
83 
84   ASSERT (!EFI_ERROR (Status));
85 
86   //
87   // Kick the event so we will perform an initial pass of
88   // current installed drivers
89   //
90 
91   gBS->SignalEvent (Event);
92   return Event;
93 }
94 
95 EFI_STATUS
EfiLibNamedEventListen(IN EFI_GUID * Name,IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,IN VOID * NotifyContext)96 EfiLibNamedEventListen (
97   IN EFI_GUID             * Name,
98   IN EFI_TPL              NotifyTpl,
99   IN EFI_EVENT_NOTIFY     NotifyFunction,
100   IN VOID                 *NotifyContext
101   )
102 /*++
103 
104 Routine Description:
105   Listenes to signals on the name.
106   EfiLibNamedEventSignal() signals the event.
107 
108   NOTE: For now, the named listening/signalling is implemented
109   on a protocol interface being installed and uninstalled.
110   In the future, this maybe implemented based on a dedicated mechanism.
111 
112 Arguments:
113   Name            - Name to register the listener on.
114   NotifyTpl       - Maximum TPL to singnal the NotifyFunction.
115   NotifyFunction  - The listener routine.
116   NotifyContext   - Context passed into the listener routine.
117 
118 Returns:
119   EFI_SUCCESS if successful.
120 
121 --*/
122 {
123   EFI_STATUS  Status;
124   EFI_EVENT   Event;
125   VOID        *RegistrationLocal;
126 
127   //
128   // Create event
129   //
130   Status = gBS->CreateEvent (
131                   EFI_EVENT_NOTIFY_SIGNAL,
132                   NotifyTpl,
133                   NotifyFunction,
134                   NotifyContext,
135                   &Event
136                   );
137   ASSERT_EFI_ERROR (Status);
138 
139   Status = gBS->RegisterProtocolNotify (
140                   Name,
141                   Event,
142                   &RegistrationLocal
143                   );
144   ASSERT_EFI_ERROR (Status);
145 
146   return EFI_SUCCESS;
147 }
148 
149 EFI_STATUS
EfiLibNamedEventSignal(IN EFI_GUID * Name)150 EfiLibNamedEventSignal (
151   IN EFI_GUID            *Name
152   )
153 /*++
154 
155 Routine Description:
156   Signals a named event. All registered listeners will run.
157   The listeners should register using EfiLibNamedEventListen() function.
158 
159   NOTE: For now, the named listening/signalling is implemented
160   on a protocol interface being installed and uninstalled.
161   In the future, this maybe implemented based on a dedicated mechanism.
162 
163 Arguments:
164   Name - Name to perform the signaling on. The name is a GUID.
165 
166 Returns:
167   EFI_SUCCESS if successfull.
168 
169 --*/
170 {
171   EFI_STATUS  Status;
172   EFI_HANDLE  Handle;
173 
174   Handle = NULL;
175   Status = gBS->InstallProtocolInterface (
176                   &Handle,
177                   Name,
178                   EFI_NATIVE_INTERFACE,
179                   NULL
180                   );
181   ASSERT_EFI_ERROR (Status);
182 
183   Status = gBS->UninstallProtocolInterface (
184                   Handle,
185                   Name,
186                   NULL
187                   );
188   ASSERT_EFI_ERROR (Status);
189 
190   return EFI_SUCCESS;
191 }
192 
193 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
194 
195 static
196 VOID
197 EFIAPI
EventNotifySignalAllNullEvent(IN EFI_EVENT Event,IN VOID * Context)198 EventNotifySignalAllNullEvent (
199   IN EFI_EVENT                Event,
200   IN VOID                     *Context
201   )
202 {
203   //
204   // This null event is a size efficent way to enusre that
205   // EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.
206   // EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into
207   // CreateEventEx() and this function is used to make the
208   // old error checking in CreateEvent() for Tiano extensions
209   // function.
210   //
211   return;
212 }
213 
214 #endif
215 
216 EFI_STATUS
217 EFIAPI
EfiCreateEventLegacyBoot(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,IN VOID * NotifyContext,OUT EFI_EVENT * LegacyBootEvent)218 EfiCreateEventLegacyBoot (
219   IN EFI_TPL                      NotifyTpl,
220   IN EFI_EVENT_NOTIFY             NotifyFunction,
221   IN VOID                         *NotifyContext,
222   OUT EFI_EVENT                   *LegacyBootEvent
223   )
224 /*++
225 
226 Routine Description:
227   Create a Legacy Boot Event.
228   Tiano extended the CreateEvent Type enum to add a legacy boot event type.
229   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
230   added and now it's possible to not voilate the UEFI specification by
231   declaring a GUID for the legacy boot event class. This library supports
232   the EFI 1.10 form and UEFI 2.0 form and allows common code to
233   work both ways.
234 
235 Arguments:
236   LegacyBootEvent  Returns the EFI event returned from gBS->CreateEvent(Ex)
237 
238 Returns:
239   EFI_SUCCESS   Event was created.
240   Other         Event was not created.
241 
242 --*/
243 {
244   EFI_STATUS        Status;
245   UINT32            EventType;
246   EFI_EVENT_NOTIFY  WorkerNotifyFunction;
247 
248 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
249 
250   if (NotifyFunction == NULL) {
251     EventType = EFI_EVENT_SIGNAL_LEGACY_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL;
252   } else {
253     EventType = EFI_EVENT_SIGNAL_LEGACY_BOOT;
254   }
255   WorkerNotifyFunction = NotifyFunction;
256 
257   //
258   // prior to UEFI 2.0 use Tiano extension to EFI
259   //
260   Status = gBS->CreateEvent (
261                   EventType,
262                   NotifyTpl,
263                   WorkerNotifyFunction,
264                   NotifyContext,
265                   LegacyBootEvent
266                   );
267 #else
268 
269   EventType = EFI_EVENT_NOTIFY_SIGNAL;
270   if (NotifyFunction == NULL) {
271     //
272     // CreatEventEx will check NotifyFunction is NULL or not
273     //
274     WorkerNotifyFunction = EventNotifySignalAllNullEvent;
275   } else {
276     WorkerNotifyFunction = NotifyFunction;
277   }
278 
279   //
280   // For UEFI 2.0 and the future use an Event Group
281   //
282   Status = gBS->CreateEventEx (
283                   EventType,
284                   NotifyTpl,
285                   WorkerNotifyFunction,
286                   NotifyContext,
287                   &gEfiEventLegacyBootGuid,
288                   LegacyBootEvent
289                   );
290 #endif
291   return Status;
292 }
293 
294 EFI_STATUS
295 EFIAPI
EfiCreateEventReadyToBoot(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,IN VOID * NotifyContext,OUT EFI_EVENT * ReadyToBootEvent)296 EfiCreateEventReadyToBoot (
297   IN EFI_TPL                      NotifyTpl,
298   IN EFI_EVENT_NOTIFY             NotifyFunction,
299   IN VOID                         *NotifyContext,
300   OUT EFI_EVENT                   *ReadyToBootEvent
301   )
302 /*++
303 
304 Routine Description:
305   Create a Read to Boot Event.
306 
307   Tiano extended the CreateEvent Type enum to add a ready to boot event type.
308   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
309   added and now it's possible to not voilate the UEFI specification and use
310   the ready to boot event class defined in UEFI 2.0. This library supports
311   the EFI 1.10 form and UEFI 2.0 form and allows common code to
312   work both ways.
313 
314 Arguments:
315   @param LegacyBootEvent  Returns the EFI event returned from gBS->CreateEvent(Ex)
316 
317 Return:
318   EFI_SUCCESS   - Event was created.
319   Other         - Event was not created.
320 
321 --*/
322 {
323   EFI_STATUS        Status;
324   UINT32            EventType;
325   EFI_EVENT_NOTIFY  WorkerNotifyFunction;
326 
327 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
328 
329   if (NotifyFunction == NULL) {
330     EventType = EFI_EVENT_SIGNAL_READY_TO_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL;
331   } else {
332     EventType = EFI_EVENT_SIGNAL_READY_TO_BOOT;
333   }
334   WorkerNotifyFunction = NotifyFunction;
335 
336   //
337   // prior to UEFI 2.0 use Tiano extension to EFI
338   //
339   Status = gBS->CreateEvent (
340                   EventType,
341                   NotifyTpl,
342                   WorkerNotifyFunction,
343                   NotifyContext,
344                   ReadyToBootEvent
345                   );
346 #else
347 
348   EventType = EFI_EVENT_NOTIFY_SIGNAL;
349   if (NotifyFunction == NULL) {
350     //
351     // CreatEventEx will check NotifyFunction is NULL or not
352     //
353     WorkerNotifyFunction = EventNotifySignalAllNullEvent;
354   } else {
355     WorkerNotifyFunction = NotifyFunction;
356   }
357 
358   //
359   // For UEFI 2.0 and the future use an Event Group
360   //
361   Status = gBS->CreateEventEx (
362                   EventType,
363                   NotifyTpl,
364                   WorkerNotifyFunction,
365                   NotifyContext,
366                   &gEfiEventReadyToBootGuid,
367                   ReadyToBootEvent
368                   );
369 #endif
370   return Status;
371 }
372