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   UefiNotTiano.c
15 
16 Abstract:
17 
18   Library functions that abstract areas of conflict between Tiano an UEFI 2.0.
19 
20   Help Port Framework/Tinao code that has conflicts with UEFI 2.0 by hiding the
21   oldconflicts with library functions and supporting implementations of the old
22   (EFI 1.10) and new (EdkII/UEFI 2.0) way.
23 
24 --*/
25 
26 #include "EdkIIGlueUefi.h"
27 
28 /**
29   An empty function to pass error checking of CreateEventEx ().
30 
31   This empty function ensures that EFI_EVENT_NOTIFY_SIGNAL_ALL is error
32   checked correctly since it is now mapped into CreateEventEx() in UEFI 2.0.
33 
34 **/
35 STATIC
36 VOID
37 EFIAPI
InternalEmptyFuntion(IN EFI_EVENT Event,IN VOID * Context)38 InternalEmptyFuntion (
39   IN EFI_EVENT                Event,
40   IN VOID                     *Context
41   )
42 {
43   return;
44 }
45 
46 /**
47   Create a Legacy Boot Event.
48 
49   Tiano extended the CreateEvent Type enum to add a legacy boot event type.
50   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
51   added and now it's possible to not voilate the UEFI specification by
52   declaring a GUID for the legacy boot event class. This library supports
53   the EDK/EFI 1.10 form and EDK II/UEFI 2.0 form and allows common code to
54   work both ways.
55 
56   @param  LegacyBootEvent   Returns the EFI event returned from gBS->CreateEvent(Ex).
57 
58   @retval EFI_SUCCESS       Event was created.
59   @retval Other             Event was not created.
60 
61 **/
62 EFI_STATUS
63 EFIAPI
GlueEfiCreateEventLegacyBoot(OUT EFI_EVENT * LegacyBootEvent)64 GlueEfiCreateEventLegacyBoot (
65   OUT EFI_EVENT  *LegacyBootEvent
66   )
67 {
68   return EfiCreateEventLegacyBootEx (
69            EFI_TPL_CALLBACK,
70            NULL,
71            NULL,
72            LegacyBootEvent
73            );
74 }
75 
76 /**
77   Create an EFI event in the Legacy Boot Event Group and allows
78   the caller to specify a notification function.
79 
80   This function abstracts the creation of the Legacy Boot Event.
81   The Framework moved from a proprietary to UEFI 2.0 based mechanism.
82   This library abstracts the caller from how this event is created to prevent
83   to code form having to change with the version of the specification supported.
84   If LegacyBootEvent is NULL, then ASSERT().
85 
86   @param  NotifyTpl         The task priority level of the event.
87   @param  NotifyFunction    The notification function to call when the event is signaled.
88   @param  NotifyContext     The content to pass to NotifyFunction when the event is signaled.
89   @param  LegacyBootEvent   Returns the EFI event returned from gBS->CreateEvent(Ex).
90 
91   @retval EFI_SUCCESS       Event was created.
92   @retval Other             Event was not created.
93 
94 **/
95 EFI_STATUS
96 EFIAPI
EfiCreateEventLegacyBootEx(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,OPTIONAL IN VOID * NotifyContext,OPTIONAL OUT EFI_EVENT * LegacyBootEvent)97 EfiCreateEventLegacyBootEx (
98   IN  EFI_TPL           NotifyTpl,
99   IN  EFI_EVENT_NOTIFY  NotifyFunction,  OPTIONAL
100   IN  VOID              *NotifyContext,  OPTIONAL
101   OUT EFI_EVENT         *LegacyBootEvent
102   )
103 {
104   EFI_STATUS        Status;
105   UINT32            EventType;
106   EFI_EVENT_NOTIFY  WorkerNotifyFunction;
107 
108   ASSERT (LegacyBootEvent != NULL);
109 
110 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
111 
112   if (NotifyFunction == NULL) {
113     EventType = EFI_EVENT_SIGNAL_LEGACY_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL;
114   } else {
115     EventType = EFI_EVENT_SIGNAL_LEGACY_BOOT;
116   }
117   WorkerNotifyFunction = NotifyFunction;
118 
119   //
120   // prior to UEFI 2.0 use Tiano extension to EFI
121   //
122   Status = gBS->CreateEvent (
123                   EventType,
124                   NotifyTpl,
125                   WorkerNotifyFunction,
126                   NotifyContext,
127                   LegacyBootEvent
128                   );
129 #else
130 
131   EventType = EVENT_NOTIFY_SIGNAL;
132   if (NotifyFunction == NULL) {
133     //
134     // CreatEventEx will check NotifyFunction is NULL or not
135     //
136     WorkerNotifyFunction = InternalEmptyFuntion;
137   } else {
138     WorkerNotifyFunction = NotifyFunction;
139   }
140 
141   //
142   // For UEFI 2.0 and the future use an Event Group
143   //
144   Status = gBS->CreateEventEx (
145                   EventType,
146                   NotifyTpl,
147                   WorkerNotifyFunction,
148                   NotifyContext,
149                   &gEfiEventLegacyBootGuid,
150                   LegacyBootEvent
151                   );
152 #endif
153 
154   return Status;
155 }
156 
157 /**
158   Create a Read to Boot Event.
159 
160   Tiano extended the CreateEvent Type enum to add a ready to boot event type.
161   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
162   added and now it's possible to not voilate the UEFI specification and use
163   the ready to boot event class defined in UEFI 2.0. This library supports
164   the EDK/EFI 1.10 form and EDK II/UEFI 2.0 form and allows common code to
165   work both ways.
166 
167   @param  LegacyBootEvent   Returns the EFI event returned from gBS->CreateEvent(Ex).
168 
169   @retval EFI_SUCCESS       Event was created.
170   @retval Other             Event was not created.
171 
172 **/
173 EFI_STATUS
174 EFIAPI
GlueEfiCreateEventReadyToBoot(OUT EFI_EVENT * ReadyToBootEvent)175 GlueEfiCreateEventReadyToBoot (
176   OUT EFI_EVENT  *ReadyToBootEvent
177   )
178 {
179   return EfiCreateEventReadyToBootEx (
180            EFI_TPL_CALLBACK,
181            NULL,
182            NULL,
183            ReadyToBootEvent
184            );
185 }
186 
187 /**
188   Create an EFI event in the Ready To Boot Event Group and allows
189   the caller to specify a notification function.
190 
191   This function abstracts the creation of the Ready to Boot Event.
192   The Framework moved from a proprietary to UEFI 2.0 based mechanism.
193   This library abstracts the caller from how this event is created to prevent
194   to code form having to change with the version of the specification supported.
195   If ReadyToBootEvent is NULL, then ASSERT().
196 
197   @param  NotifyTpl         The task priority level of the event.
198   @param  NotifyFunction    The notification function to call when the event is signaled.
199   @param  NotifyContext     The content to pass to NotifyFunction when the event is signaled.
200   @param  LegacyBootEvent   Returns the EFI event returned from gBS->CreateEvent(Ex).
201 
202   @retval EFI_SUCCESS       Event was created.
203   @retval Other             Event was not created.
204 
205 **/
206 EFI_STATUS
207 EFIAPI
EfiCreateEventReadyToBootEx(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,OPTIONAL IN VOID * NotifyContext,OPTIONAL OUT EFI_EVENT * ReadyToBootEvent)208 EfiCreateEventReadyToBootEx (
209   IN  EFI_TPL           NotifyTpl,
210   IN  EFI_EVENT_NOTIFY  NotifyFunction,  OPTIONAL
211   IN  VOID              *NotifyContext,  OPTIONAL
212   OUT EFI_EVENT         *ReadyToBootEvent
213   )
214 {
215   EFI_STATUS        Status;
216   UINT32            EventType;
217   EFI_EVENT_NOTIFY	WorkerNotifyFunction;
218 
219   ASSERT (ReadyToBootEvent != NULL);
220 
221 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
222 
223   if (NotifyFunction == NULL) {
224 	EventType = EFI_EVENT_SIGNAL_READY_TO_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL;
225   } else {
226 	EventType = EFI_EVENT_SIGNAL_READY_TO_BOOT;
227   }
228   WorkerNotifyFunction = NotifyFunction;
229 
230   //
231   // prior to UEFI 2.0 use Tiano extension to EFI
232   //
233   Status = gBS->CreateEvent (
234                   EventType,
235                   NotifyTpl,
236                   WorkerNotifyFunction,
237                   NotifyContext,
238                   ReadyToBootEvent
239                   );
240 #else
241 
242   EventType = EVENT_NOTIFY_SIGNAL;
243 
244   if (NotifyFunction == NULL) {
245     //
246     // CreatEventEx will check NotifyFunction is NULL or not
247     //
248     WorkerNotifyFunction = InternalEmptyFuntion;
249   } else {
250     WorkerNotifyFunction = NotifyFunction;
251   }
252 
253   //
254   // For UEFI 2.0 and the future use an Event Group
255   //
256   Status = gBS->CreateEventEx (
257                   EventType,
258                   NotifyTpl,
259                   WorkerNotifyFunction,
260                   NotifyContext,
261                   &gEfiEventReadyToBootGuid,
262                   ReadyToBootEvent
263                   );
264 #endif
265 
266   return Status;
267 }
268 
269 
270 /**
271   Signal a Ready to Boot Event.
272 
273   Create a Ready to Boot Event. Signal it and close it. This causes other
274   events of the same event group to be signaled in other modules.
275 
276 **/
277 VOID
278 EFIAPI
EfiSignalEventReadyToBoot(VOID)279 EfiSignalEventReadyToBoot (
280   VOID
281   )
282 {
283   EFI_STATUS    Status;
284   EFI_EVENT     ReadyToBootEvent;
285 
286   Status = EfiCreateEventReadyToBoot (&ReadyToBootEvent);
287   if (!EFI_ERROR (Status)) {
288     gBS->SignalEvent (ReadyToBootEvent);
289     gBS->CloseEvent (ReadyToBootEvent);
290   }
291 }
292 
293 /**
294   Signal a Legacy Boot Event.
295 
296   Create a legacy Boot Event. Signal it and close it. This causes other
297   events of the same event group to be signaled in other modules.
298 
299 **/
300 VOID
301 EFIAPI
EfiSignalEventLegacyBoot(VOID)302 EfiSignalEventLegacyBoot (
303   VOID
304   )
305 {
306   EFI_STATUS    Status;
307   EFI_EVENT     LegacyBootEvent;
308 
309   Status = EfiCreateEventLegacyBoot (&LegacyBootEvent);
310   if (!EFI_ERROR (Status)) {
311     gBS->SignalEvent (LegacyBootEvent);
312     gBS->CloseEvent (LegacyBootEvent);
313   }
314 }
315 
316 
317 /**
318   Check to see if the Firmware Volume (FV) Media Device Path is valid
319 
320   @param  FvDevicePathNode  Pointer to FV device path to check.
321 
322   @retval NULL              FvDevicePathNode is not valid.
323   @retval Other             FvDevicePathNode is valid and pointer to NameGuid was returned.
324 
325 **/
326 EFI_GUID *
327 EFIAPI
GlueEfiGetNameGuidFromFwVolDevicePathNode(IN CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH * FvDevicePathNode)328 GlueEfiGetNameGuidFromFwVolDevicePathNode (
329   IN CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvDevicePathNode
330   )
331 {
332   ASSERT (FvDevicePathNode != NULL);
333 
334   if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
335       DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {
336     return (EFI_GUID *) &FvDevicePathNode->NameGuid;
337   }
338 
339   return NULL;
340 }
341 
342 
343 /**
344   Initialize a Firmware Volume (FV) Media Device Path node.
345 
346   @param  FvDevicePathNode  Pointer to a FV device path node to initialize
347   @param  NameGuid          FV file name to use in FvDevicePathNode
348 
349 **/
350 VOID
351 EFIAPI
GlueEfiInitializeFwVolDevicepathNode(IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH * FvDevicePathNode,IN CONST EFI_GUID * NameGuid)352 GlueEfiInitializeFwVolDevicepathNode (
353   IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvDevicePathNode,
354   IN CONST EFI_GUID                         *NameGuid
355   )
356 {
357   ASSERT (FvDevicePathNode  != NULL);
358   ASSERT (NameGuid          != NULL);
359 
360   FvDevicePathNode->Header.Type     = MEDIA_DEVICE_PATH;
361   FvDevicePathNode->Header.SubType  = MEDIA_FV_FILEPATH_DP;
362   SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
363 
364   CopyGuid (&FvDevicePathNode->NameGuid, NameGuid);
365 }
366 
367