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 "EfiRuntimeLib.h"
24 
25 EFI_EVENT
RtEfiLibCreateProtocolNotifyEvent(IN EFI_GUID * ProtocolGuid,IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,IN VOID * NotifyContext,OUT VOID ** Registration)26 RtEfiLibCreateProtocolNotifyEvent (
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   Status = gBS->CreateEvent (
65                   EFI_EVENT_NOTIFY_SIGNAL,
66                   NotifyTpl,
67                   NotifyFunction,
68                   NotifyContext,
69                   &Event
70                   );
71   ASSERT (!EFI_ERROR (Status));
72 
73   //
74   // Register for protocol notifactions on this event
75   //
76   Status = gBS->RegisterProtocolNotify (
77                   ProtocolGuid,
78                   Event,
79                   Registration
80                   );
81 
82   ASSERT (!EFI_ERROR (Status));
83 
84   //
85   // Kick the event so we will perform an initial pass of
86   // current installed drivers
87   //
88   gBS->SignalEvent (Event);
89   return Event;
90 }
91 
92 EFI_STATUS
EfiLibGetSystemConfigurationTable(IN EFI_GUID * TableGuid,IN OUT VOID ** Table)93 EfiLibGetSystemConfigurationTable (
94   IN EFI_GUID *TableGuid,
95   IN OUT VOID **Table
96   )
97 /*++
98 
99 Routine Description:
100 
101   Return the EFI 1.0 System Tabl entry with TableGuid
102 
103 Arguments:
104 
105   TableGuid - Name of entry to return in the system table
106   Table     - Pointer in EFI system table associated with TableGuid
107 
108 Returns:
109 
110   EFI_SUCCESS - Table returned;
111   EFI_NOT_FOUND - TableGuid not in EFI system table
112 
113 --*/
114 {
115   UINTN Index;
116 
117   for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
118     if (EfiCompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
119       *Table = gST->ConfigurationTable[Index].VendorTable;
120       return EFI_SUCCESS;
121     }
122   }
123 
124   return EFI_NOT_FOUND;
125 }
126 
127 EFI_STATUS
EfiConvertList(IN UINTN DebugDisposition,IN OUT EFI_LIST_ENTRY * ListHead)128 EfiConvertList (
129   IN UINTN                DebugDisposition,
130   IN OUT EFI_LIST_ENTRY   *ListHead
131   )
132 /*++
133 
134 Routine Description:
135 
136   Conver the standard Lib double linked list to a virtual mapping.
137 
138 Arguments:
139 
140   DebugDisposition - Argument to EfiConvertPointer (EFI 1.0 API)
141 
142   ListHead         - Head of linked list to convert
143 
144 Returns:
145 
146   EFI_SUCCESS
147 
148 --*/
149 {
150   EFI_LIST_ENTRY  *Link;
151   EFI_LIST_ENTRY  *NextLink;
152 
153   //
154   // Convert all the ForwardLink & BackLink pointers in the list
155   //
156   Link = ListHead;
157   do {
158     NextLink = Link->ForwardLink;
159 
160     EfiConvertPointer (
161       Link->ForwardLink == ListHead ? DebugDisposition : 0,
162       (VOID **) &Link->ForwardLink
163       );
164 
165     EfiConvertPointer (
166       Link->BackLink == ListHead ? DebugDisposition : 0,
167       (VOID **) &Link->BackLink
168       );
169 
170     Link = NextLink;
171   } while (Link != ListHead);
172   return EFI_SUCCESS;
173 }
174 
175 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
176 
177 STATIC
178 VOID
179 EFIAPI
EventNotifySignalAllNullEvent(IN EFI_EVENT Event,IN VOID * Context)180 EventNotifySignalAllNullEvent (
181   IN EFI_EVENT                Event,
182   IN VOID                     *Context
183   )
184 {
185   //
186   // This null event is a size efficent way to enusre that
187   // EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.
188   // EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into
189   // CreateEventEx() and this function is used to make the
190   // old error checking in CreateEvent() for Tiano extensions
191   // function.
192   //
193   return;
194 }
195 
196 #endif
197 
198 EFI_STATUS
199 EFIAPI
RtEfiCreateEventLegacyBoot(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,IN VOID * NotifyContext,OUT EFI_EVENT * LegacyBootEvent)200 RtEfiCreateEventLegacyBoot (
201   IN EFI_TPL                      NotifyTpl,
202   IN EFI_EVENT_NOTIFY             NotifyFunction,
203   IN VOID                         *NotifyContext,
204   OUT EFI_EVENT                   *LegacyBootEvent
205   )
206 /*++
207 
208 Routine Description:
209   Create a Legacy Boot Event.
210   Tiano extended the CreateEvent Type enum to add a legacy boot event type.
211   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
212   added and now it's possible to not voilate the UEFI specification by
213   declaring a GUID for the legacy boot event class. This library supports
214   the EFI 1.10 form and UEFI 2.0 form and allows common code to work both ways.
215 
216 Arguments:
217   LegacyBootEvent  Returns the EFI event returned from gBS->CreateEvent(Ex)
218 
219 Returns:
220   EFI_SUCCESS   Event was created.
221   Other         Event was not created.
222 
223 --*/
224 {
225   EFI_STATUS        Status;
226   UINT32            EventType;
227   EFI_EVENT_NOTIFY  WorkerNotifyFunction;
228 
229 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
230 
231   if (NotifyFunction == NULL) {
232     EventType = EFI_EVENT_SIGNAL_LEGACY_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL;
233   } else {
234     EventType = EFI_EVENT_SIGNAL_LEGACY_BOOT;
235   }
236   WorkerNotifyFunction = NotifyFunction;
237 
238   //
239   // prior to UEFI 2.0 use Tiano extension to EFI
240   //
241   Status = gBS->CreateEvent (
242                   EventType,
243                   NotifyTpl,
244                   WorkerNotifyFunction,
245                   NotifyContext,
246                   LegacyBootEvent
247                   );
248 #else
249 
250   EventType = EFI_EVENT_NOTIFY_SIGNAL;
251   if (NotifyFunction == NULL) {
252     //
253     // CreatEventEx will check NotifyFunction is NULL or not
254     //
255     WorkerNotifyFunction = EventNotifySignalAllNullEvent;
256   } else {
257     WorkerNotifyFunction = NotifyFunction;
258   }
259 
260   //
261   // For UEFI 2.0 and the future use an Event Group
262   //
263   Status = gBS->CreateEventEx (
264                   EventType,
265                   NotifyTpl,
266                   WorkerNotifyFunction,
267                   NotifyContext,
268                   &gEfiEventLegacyBootGuid,
269                   LegacyBootEvent
270                   );
271 #endif
272   return Status;
273 }
274 
275 EFI_STATUS
276 EFIAPI
RtEfiCreateEventReadyToBoot(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,IN VOID * NotifyContext,OUT EFI_EVENT * ReadyToBootEvent)277 RtEfiCreateEventReadyToBoot (
278   IN EFI_TPL                      NotifyTpl,
279   IN EFI_EVENT_NOTIFY             NotifyFunction,
280   IN VOID                         *NotifyContext,
281   OUT EFI_EVENT                   *ReadyToBootEvent
282   )
283 /*++
284 
285 Routine Description:
286   Create a Read to Boot Event.
287 
288   Tiano extended the CreateEvent Type enum to add a ready to boot event type.
289   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
290   added and now it's possible to not voilate the UEFI specification and use
291   the ready to boot event class defined in UEFI 2.0. This library supports
292   the EFI 1.10 form and UEFI 2.0 form and allows common code to work both ways.
293 
294 Arguments:
295   ReadyToBootEvent  Returns the EFI event returned from gBS->CreateEvent(Ex)
296 
297 Return:
298   EFI_SUCCESS   - Event was created.
299   Other         - Event was not created.
300 
301 --*/
302 {
303   EFI_STATUS        Status;
304   UINT32            EventType;
305   EFI_EVENT_NOTIFY  WorkerNotifyFunction;
306 
307 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
308 
309   if (NotifyFunction == NULL) {
310     EventType = EFI_EVENT_SIGNAL_READY_TO_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL;
311   } else {
312     EventType = EFI_EVENT_SIGNAL_READY_TO_BOOT;
313   }
314   WorkerNotifyFunction = NotifyFunction;
315 
316   //
317   // prior to UEFI 2.0 use Tiano extension to EFI
318   //
319   Status = gBS->CreateEvent (
320                   EventType,
321                   NotifyTpl,
322                   WorkerNotifyFunction,
323                   NotifyContext,
324                   ReadyToBootEvent
325                   );
326 #else
327 
328   EventType = EFI_EVENT_NOTIFY_SIGNAL;
329   if (NotifyFunction == NULL) {
330     //
331     // CreatEventEx will check NotifyFunction is NULL or not
332     //
333     WorkerNotifyFunction = EventNotifySignalAllNullEvent;
334   } else {
335     WorkerNotifyFunction = NotifyFunction;
336   }
337 
338   //
339   // For UEFI 2.0 and the future use an Event Group
340   //
341   Status = gBS->CreateEventEx (
342                   EventType,
343                   NotifyTpl,
344                   WorkerNotifyFunction,
345                   NotifyContext,
346                   &gEfiEventReadyToBootGuid,
347                   ReadyToBootEvent
348                   );
349 #endif
350   return Status;
351 }
352