1 /** @file
2   Library functions that abstract areas of conflict between framework and UEFI 2.0.
3 
4   Help Port Framework code that has conflicts with UEFI 2.0 by hiding the
5   old conflicts with library functions and supporting implementations of the old
6   (EDK/EFI 1.10) and new (EDK II/UEFI 2.0) way. This module is a DXE driver as
7   it contains DXE enum extensions for EFI event services.
8 
9 Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>
10 This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution.  The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
14 
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 
18 **/
19 
20 
21 
22 #include "UefiLibInternal.h"
23 
24 /**
25   An empty function to pass error checking of CreateEventEx ().
26 
27   This empty function ensures that EVT_NOTIFY_SIGNAL_ALL is error
28   checked correctly since it is now mapped into CreateEventEx() in UEFI 2.0.
29 
30   @param  Event                 Event whose notification function is being invoked.
31   @param  Context               Pointer to the notification function's context,
32                                 which is implementation-dependent.
33 
34 **/
35 VOID
36 EFIAPI
InternalEmptyFuntion(IN EFI_EVENT Event,IN VOID * Context)37 InternalEmptyFuntion (
38   IN EFI_EVENT                Event,
39   IN VOID                     *Context
40   )
41 {
42   return;
43 }
44 
45 /**
46   Create a Legacy Boot Event.
47 
48   Tiano extended the CreateEvent Type enum to add a legacy boot event type.
49   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
50   added and now it's possible to not voilate the UEFI specification by
51   declaring a GUID for the legacy boot event class. This library supports
52   the EDK/EFI 1.10 form and EDK II/UEFI 2.0 form and allows common code to
53   work both ways.
54 
55   @param  LegacyBootEvent   Returns the EFI event returned from gBS->CreateEvent(Ex).
56 
57   @retval EFI_SUCCESS       Event was created.
58   @retval Other             Event was not created.
59 
60 **/
61 EFI_STATUS
62 EFIAPI
EfiCreateEventLegacyBoot(OUT EFI_EVENT * LegacyBootEvent)63 EfiCreateEventLegacyBoot (
64   OUT EFI_EVENT  *LegacyBootEvent
65   )
66 {
67   return EfiCreateEventLegacyBootEx (
68            TPL_CALLBACK,
69            InternalEmptyFuntion,
70            NULL,
71            LegacyBootEvent
72            );
73 }
74 
75 /**
76   Create an EFI event in the Legacy Boot Event Group and allows
77   the caller to specify a notification function.
78 
79   This function abstracts the creation of the Legacy Boot Event.
80   The Framework moved from a proprietary to UEFI 2.0 based mechanism.
81   This library abstracts the caller from how this event is created to prevent
82   to code form having to change with the version of the specification supported.
83   If LegacyBootEvent is NULL, then ASSERT().
84 
85   @param  NotifyTpl         The task priority level of the event.
86   @param  NotifyFunction    The notification function to call when the event is signaled.
87   @param  NotifyContext     The content to pass to NotifyFunction when the event is signaled.
88   @param  LegacyBootEvent   Returns the EFI event returned from gBS->CreateEvent(Ex).
89 
90   @retval EFI_SUCCESS       Event was created.
91   @retval Other             Event was not created.
92 
93 **/
94 EFI_STATUS
95 EFIAPI
EfiCreateEventLegacyBootEx(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,OPTIONAL IN VOID * NotifyContext,OPTIONAL OUT EFI_EVENT * LegacyBootEvent)96 EfiCreateEventLegacyBootEx (
97   IN  EFI_TPL           NotifyTpl,
98   IN  EFI_EVENT_NOTIFY  NotifyFunction,  OPTIONAL
99   IN  VOID              *NotifyContext,  OPTIONAL
100   OUT EFI_EVENT         *LegacyBootEvent
101   )
102 {
103   EFI_STATUS    Status;
104 
105   ASSERT (LegacyBootEvent != NULL);
106 
107   if (gST->Hdr.Revision < 0x00020000) {
108     //
109     // prior to UEFI 2.0 use Tiano extension to EFI
110     //
111     Status = gBS->CreateEvent (
112                     EFI_EVENT_SIGNAL_LEGACY_BOOT | EVT_NOTIFY_SIGNAL,
113                     NotifyTpl,
114                     NotifyFunction,
115                     NotifyContext,
116                     LegacyBootEvent
117                     );
118   } else {
119     //
120     // For UEFI 2.0 and the future use an Event Group
121     //
122     Status = gBS->CreateEventEx (
123                     EVT_NOTIFY_SIGNAL,
124                     NotifyTpl,
125                     NotifyFunction,
126                     NotifyContext,
127                     &gEfiEventLegacyBootGuid,
128                     LegacyBootEvent
129                     );
130   }
131 
132   return Status;
133 }
134 
135 /**
136   Create a Read to Boot Event.
137 
138   Tiano extended the CreateEvent Type enum to add a ready to boot event type.
139   This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was
140   added and now it's possible to not voilate the UEFI specification and use
141   the ready to boot event class defined in UEFI 2.0. This library supports
142   the EDK/EFI 1.10 form and EDK II/UEFI 2.0 form and allows common code to
143   work both ways.
144 
145   @param  ReadyToBootEvent   Returns the EFI event returned from gBS->CreateEvent(Ex).
146 
147   @retval EFI_SUCCESS       Event was created.
148   @retval Other             Event was not created.
149 
150 **/
151 EFI_STATUS
152 EFIAPI
EfiCreateEventReadyToBoot(OUT EFI_EVENT * ReadyToBootEvent)153 EfiCreateEventReadyToBoot (
154   OUT EFI_EVENT  *ReadyToBootEvent
155   )
156 {
157   return EfiCreateEventReadyToBootEx (
158            TPL_CALLBACK,
159            InternalEmptyFuntion,
160            NULL,
161            ReadyToBootEvent
162            );
163 }
164 
165 /**
166   Create an EFI event in the Ready To Boot Event Group and allows
167   the caller to specify a notification function.
168 
169   This function abstracts the creation of the Ready to Boot Event.
170   The Framework moved from a proprietary to UEFI 2.0 based mechanism.
171   This library abstracts the caller from how this event is created to prevent
172   to code form having to change with the version of the specification supported.
173   If ReadyToBootEvent is NULL, then ASSERT().
174 
175   @param  NotifyTpl         The task priority level of the event.
176   @param  NotifyFunction    The notification function to call when the event is signaled.
177   @param  NotifyContext     The content to pass to NotifyFunction when the event is signaled.
178   @param  ReadyToBootEvent  Returns the EFI event returned from gBS->CreateEvent(Ex).
179 
180   @retval EFI_SUCCESS       Event was created.
181   @retval Other             Event was not created.
182 
183 **/
184 EFI_STATUS
185 EFIAPI
EfiCreateEventReadyToBootEx(IN EFI_TPL NotifyTpl,IN EFI_EVENT_NOTIFY NotifyFunction,OPTIONAL IN VOID * NotifyContext,OPTIONAL OUT EFI_EVENT * ReadyToBootEvent)186 EfiCreateEventReadyToBootEx (
187   IN  EFI_TPL           NotifyTpl,
188   IN  EFI_EVENT_NOTIFY  NotifyFunction,  OPTIONAL
189   IN  VOID              *NotifyContext,  OPTIONAL
190   OUT EFI_EVENT         *ReadyToBootEvent
191   )
192 {
193   EFI_STATUS    Status;
194 
195   ASSERT (ReadyToBootEvent != NULL);
196 
197   if (gST->Hdr.Revision < 0x00020000) {
198     //
199     // prior to UEFI 2.0 use Tiano extension to EFI
200     //
201     Status = gBS->CreateEvent (
202                     EFI_EVENT_SIGNAL_READY_TO_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL,
203                     NotifyTpl,
204                     NotifyFunction,
205                     NotifyContext,
206                     ReadyToBootEvent
207                     );
208   } else {
209     //
210     // For UEFI 2.0 and the future use an Event Group
211     //
212     Status = gBS->CreateEventEx (
213                     EVT_NOTIFY_SIGNAL,
214                     NotifyTpl,
215                     NotifyFunction,
216                     NotifyContext,
217                     &gEfiEventReadyToBootGuid,
218                     ReadyToBootEvent
219                     );
220   }
221 
222   return Status;
223 }
224 
225 
226 /**
227   Signal a Ready to Boot Event.
228 
229   Create a Ready to Boot Event. Signal it and close it. This causes other
230   events of the same event group to be signaled in other modules.
231 
232 **/
233 VOID
234 EFIAPI
EfiSignalEventReadyToBoot(VOID)235 EfiSignalEventReadyToBoot (
236   VOID
237   )
238 {
239   EFI_STATUS    Status;
240   EFI_EVENT     ReadyToBootEvent;
241 
242   Status = EfiCreateEventReadyToBoot (&ReadyToBootEvent);
243   if (!EFI_ERROR (Status)) {
244     gBS->SignalEvent (ReadyToBootEvent);
245     gBS->CloseEvent (ReadyToBootEvent);
246   }
247 }
248 
249 /**
250   Signal a Legacy Boot Event.
251 
252   Create a legacy Boot Event. Signal it and close it. This causes other
253   events of the same event group to be signaled in other modules.
254 
255 **/
256 VOID
257 EFIAPI
EfiSignalEventLegacyBoot(VOID)258 EfiSignalEventLegacyBoot (
259   VOID
260   )
261 {
262   EFI_STATUS    Status;
263   EFI_EVENT     LegacyBootEvent;
264 
265   Status = EfiCreateEventLegacyBoot (&LegacyBootEvent);
266   if (!EFI_ERROR (Status)) {
267     gBS->SignalEvent (LegacyBootEvent);
268     gBS->CloseEvent (LegacyBootEvent);
269   }
270 }
271 
272 
273 /**
274   Check to see if the Firmware Volume (FV) Media Device Path is valid
275 
276   Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
277   so as we move to UEFI 2.0 support we must use a mechanism that conforms with
278   the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
279   device path is defined for Tiano extensions of device path. If the code
280   is compiled to conform with the UEFI 2.0 specification use the new device path
281   else use the old form for backwards compatability. The return value to this
282   function points to a location in FvDevicePathNode and it does not allocate
283   new memory for the GUID pointer that is returned.
284 
285   @param  FvDevicePathNode  Pointer to FV device path to check.
286 
287   @retval NULL              FvDevicePathNode is not valid.
288   @retval Other             FvDevicePathNode is valid and pointer to NameGuid was returned.
289 
290 **/
291 EFI_GUID *
292 EFIAPI
EfiGetNameGuidFromFwVolDevicePathNode(IN CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH * FvDevicePathNode)293 EfiGetNameGuidFromFwVolDevicePathNode (
294   IN CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvDevicePathNode
295   )
296 {
297   ASSERT (FvDevicePathNode != NULL);
298 
299   //
300   // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10.
301   // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with
302   // EFI 1.10 and UEFI 2.10.
303   //
304   if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
305       DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_PIWG_FW_FILE_DP) {
306     return (EFI_GUID *) &FvDevicePathNode->FvFileName;
307   }
308 
309   return NULL;
310 }
311 
312 
313 /**
314   Initialize a Firmware Volume (FV) Media Device Path node.
315 
316   Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
317   so as we move to UEFI 2.0 support we must use a mechanism that conforms with
318   the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
319   device path is defined for Tiano extensions of device path. If the code
320   is compiled to conform with the UEFI 2.0 specification use the new device path
321   else use the old form for backwards compatability.
322 
323   @param  FvDevicePathNode  Pointer to a FV device path node to initialize
324   @param  NameGuid          FV file name to use in FvDevicePathNode
325 
326 **/
327 VOID
328 EFIAPI
EfiInitializeFwVolDevicepathNode(IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH * FvDevicePathNode,IN CONST EFI_GUID * NameGuid)329 EfiInitializeFwVolDevicepathNode (
330   IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvDevicePathNode,
331   IN CONST EFI_GUID                         *NameGuid
332   )
333 {
334   ASSERT (FvDevicePathNode  != NULL);
335   ASSERT (NameGuid          != NULL);
336 
337   //
338   // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10.
339   // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with
340   // EFI 1.10 and UEFI 2.10.
341   //
342   FvDevicePathNode->Header.Type     = MEDIA_DEVICE_PATH;
343   FvDevicePathNode->Header.SubType  = MEDIA_PIWG_FW_FILE_DP;
344   SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
345 
346   CopyGuid (&FvDevicePathNode->FvFileName, NameGuid);
347 }
348 
349