Home | History | Annotate | Download | only in EfiDriverLib
      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
     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
     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
    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
    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
    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
    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