1/*	$NetBSD: event.c,v 1.3 2018/08/16 18:22:05 jmcneill Exp $	*/
2
3/*++
4
5Copyright (c) 1998  Intel Corporation
6
7Module Name:
8
9    event.c
10
11Abstract:
12
13
14
15
16Revision History
17
18--*/
19
20#include "lib.h"
21
22
23EFI_EVENT
24LibCreateProtocolNotifyEvent (
25    IN EFI_GUID             *ProtocolGuid,
26    IN EFI_TPL              NotifyTpl,
27    IN EFI_EVENT_NOTIFY     NotifyFunction,
28    IN VOID                 *NotifyContext,
29    OUT VOID                *Registration
30    )
31{
32#ifdef EFI_DEBUG
33    EFI_STATUS              Status;
34#else
35    EFI_STATUS              Status __unused;
36#endif
37    EFI_EVENT               Event;
38
39    //
40    // Create the event
41    //
42
43    Status = uefi_call_wrapper(
44		    BS->CreateEvent,
45			5,
46		    EVT_NOTIFY_SIGNAL,
47		    NotifyTpl,
48		    NotifyFunction,
49		    NotifyContext,
50		    &Event
51		    );
52    if ( EFI_ERROR( Status ) ) return NULL ;
53    ASSERT (!EFI_ERROR(Status));
54
55    //
56    // Register for protocol notifactions on this event
57    //
58
59    Status = uefi_call_wrapper(
60		    BS->RegisterProtocolNotify,
61			3,
62                    ProtocolGuid,
63                    Event,
64                    Registration
65                    );
66    if ( EFI_ERROR( Status ) ) return NULL ;
67    ASSERT (!EFI_ERROR(Status));
68
69    //
70    // Kick the event so we will perform an initial pass of
71    // current installed drivers
72    //
73
74    uefi_call_wrapper(BS->SignalEvent, 1, Event);
75    return Event;
76}
77
78
79EFI_STATUS
80WaitForSingleEvent (
81    IN EFI_EVENT        Event,
82    IN UINT64           Timeout OPTIONAL
83    )
84{
85    EFI_STATUS          Status;
86    UINTN               Index;
87    EFI_EVENT           TimerEvent;
88    EFI_EVENT           WaitList[2];
89
90    if (Timeout) {
91        //
92        // Create a timer event
93        //
94
95        Status = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &TimerEvent);
96        if (!EFI_ERROR(Status)) {
97
98            //
99            // Set the timer event
100            //
101
102            uefi_call_wrapper(BS->SetTimer, 3, TimerEvent, TimerRelative, Timeout);
103
104            //
105            // Wait for the original event or the timer
106            //
107
108            WaitList[0] = Event;
109            WaitList[1] = TimerEvent;
110            Status = uefi_call_wrapper(BS->WaitForEvent, 3, 2, WaitList, &Index);
111            uefi_call_wrapper(BS->CloseEvent, 1, TimerEvent);
112
113            //
114            // If the timer expired, change the return to timed out
115            //
116
117            if (!EFI_ERROR(Status)  &&  Index == 1) {
118                Status = EFI_TIMEOUT;
119            }
120        }
121
122    } else {
123
124        //
125        // No timeout... just wait on the event
126        //
127
128        Status = uefi_call_wrapper(BS->WaitForEvent, 3, 1, &Event, &Index);
129        ASSERT (!EFI_ERROR(Status));
130        ASSERT (Index == 0);
131    }
132
133    return Status;
134}
135
136VOID
137WaitForEventWithTimeout (
138    IN  EFI_EVENT       Event,
139    IN  UINTN           Timeout,
140    IN  UINTN           Row,
141    IN  UINTN           Column,
142    IN  CHAR16          *String,
143    IN  EFI_INPUT_KEY   TimeoutKey,
144    OUT EFI_INPUT_KEY   *Key
145    )
146{
147    EFI_STATUS      Status;
148
149    do {
150        PrintAt (Column, Row, String, Timeout);
151        Status = WaitForSingleEvent (Event, 10000000);
152        if (Status == EFI_SUCCESS) {
153            if (!EFI_ERROR(uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, Key))) {
154                return;
155            }
156        }
157    } while (Timeout > 0);
158    CopyMem(Key, &TimeoutKey, sizeof(EFI_INPUT_KEY));
159}
160
161