]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Event/Event.c
1) Add type cast for better coding style.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Event / Event.c
CommitLineData
23c98c94 1/** @file\r
504214c4
LG
2 UEFI Event support functions implemented in this file.\r
3\r
720f84a9 4Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
28a00297 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
504214c4 13**/\r
28a00297 14\r
15\r
9c4ac31c 16#include "DxeMain.h"\r
ec90508b 17#include "Event.h"\r
28a00297 18\r
1947c70c 19///\r
20/// gEfiCurrentTpl - Current Task priority level\r
21///\r
22EFI_TPL gEfiCurrentTpl = TPL_APPLICATION;\r
23\r
24///\r
d613c2a8 25/// gEventQueueLock - Protects the event queues\r
1947c70c 26///\r
27EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);\r
28\r
29///\r
30/// gEventQueue - A list of event's to notify for each priority level\r
31///\r
32LIST_ENTRY gEventQueue[TPL_HIGH_LEVEL + 1];\r
33\r
34///\r
35/// gEventPending - A bitmask of the EventQueues that are pending\r
36///\r
37UINTN gEventPending = 0;\r
38\r
39///\r
40/// gEventSignalQueue - A list of events to signal based on EventGroup type\r
41///\r
42LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue);\r
43\r
44///\r
45/// Enumerate the valid types\r
46///\r
28a00297 47UINT32 mEventTable[] = {\r
1947c70c 48 ///\r
49 /// 0x80000200 Timer event with a notification function that is\r
50 /// queue when the event is signaled with SignalEvent()\r
51 ///\r
28a00297 52 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1947c70c 53 ///\r
54 /// 0x80000000 Timer event without a notification function. It can be\r
55 /// signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().\r
56 ///\r
28a00297 57 EVT_TIMER,\r
1947c70c 58 ///\r
59 /// 0x00000100 Generic event with a notification function that\r
60 /// can be waited on with CheckEvent() or WaitForEvent()\r
61 ///\r
28a00297 62 EVT_NOTIFY_WAIT,\r
1947c70c 63 ///\r
64 /// 0x00000200 Generic event with a notification function that\r
65 /// is queue when the event is signaled with SignalEvent()\r
66 ///\r
28a00297 67 EVT_NOTIFY_SIGNAL,\r
1947c70c 68 ///\r
69 /// 0x00000201 ExitBootServicesEvent.\r
70 ///\r
28a00297 71 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
1947c70c 72 ///\r
73 /// 0x60000202 SetVirtualAddressMapEvent.\r
74 ///\r
28a00297 75 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
76\r
1947c70c 77 ///\r
78 /// 0x00000000 Generic event without a notification function.\r
79 /// It can be signaled with SignalEvent() and checked with CheckEvent()\r
80 /// or WaitForEvent().\r
81 ///\r
28a00297 82 0x00000000,\r
1947c70c 83 ///\r
84 /// 0x80000100 Timer event with a notification function that can be\r
85 /// waited on with CheckEvent() or WaitForEvent()\r
86 ///\r
28a00297 87 EVT_TIMER | EVT_NOTIFY_WAIT,\r
88};\r
89\r
54cd17e9 90///\r
91/// gIdleLoopEvent - Event which is signalled when the core is idle\r
92///\r
93EFI_EVENT gIdleLoopEvent = NULL;\r
94\r
162ed594 95\r
96/**\r
97 Enter critical section by acquiring the lock on gEventQueueLock.\r
98\r
99**/\r
28a00297 100VOID\r
101CoreAcquireEventLock (\r
102 VOID\r
103 )\r
28a00297 104{\r
105 CoreAcquireLock (&gEventQueueLock);\r
106}\r
107\r
162ed594 108\r
109/**\r
110 Exit critical section by releasing the lock on gEventQueueLock.\r
111\r
112**/\r
28a00297 113VOID\r
114CoreReleaseEventLock (\r
115 VOID\r
116 )\r
28a00297 117{\r
118 CoreReleaseLock (&gEventQueueLock);\r
119}\r
120\r
121\r
28a00297 122\r
162ed594 123/**\r
c18f12d3 124 Initializes "event" support.\r
28a00297 125\r
162ed594 126 @retval EFI_SUCCESS Always return success\r
28a00297 127\r
162ed594 128**/\r
129EFI_STATUS\r
130CoreInitializeEventServices (\r
131 VOID\r
132 )\r
28a00297 133{\r
134 UINTN Index;\r
135\r
136 for (Index=0; Index <= TPL_HIGH_LEVEL; Index++) {\r
137 InitializeListHead (&gEventQueue[Index]);\r
138 }\r
139\r
140 CoreInitializeTimer ();\r
141\r
54cd17e9 142 CoreCreateEventEx (\r
143 EVT_NOTIFY_SIGNAL,\r
144 TPL_NOTIFY,\r
145 CoreEmptyCallbackFunction,\r
146 NULL,\r
147 &gIdleLoopEventGuid,\r
148 &gIdleLoopEvent\r
149 );\r
150\r
28a00297 151 return EFI_SUCCESS;\r
152}\r
153\r
154\r
28a00297 155\r
162ed594 156/**\r
28a00297 157 Dispatches all pending events.\r
158\r
022c6d45 159 @param Priority The task priority level of event notifications\r
162ed594 160 to dispatch\r
28a00297 161\r
162ed594 162**/\r
163VOID\r
164CoreDispatchEventNotifies (\r
165 IN EFI_TPL Priority\r
166 )\r
28a00297 167{\r
168 IEVENT *Event;\r
169 LIST_ENTRY *Head;\r
170\r
171 CoreAcquireEventLock ();\r
172 ASSERT (gEventQueueLock.OwnerTpl == Priority);\r
173 Head = &gEventQueue[Priority];\r
174\r
175 //\r
176 // Dispatch all the pending notifications\r
177 //\r
178 while (!IsListEmpty (Head)) {\r
179\r
180 Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);\r
181 RemoveEntryList (&Event->NotifyLink);\r
182\r
183 Event->NotifyLink.ForwardLink = NULL;\r
184\r
185 //\r
186 // Only clear the SIGNAL status if it is a SIGNAL type event.\r
187 // WAIT type events are only cleared in CheckEvent()\r
188 //\r
6e536468 189 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 190 Event->SignalCount = 0;\r
191 }\r
192\r
193 CoreReleaseEventLock ();\r
194\r
195 //\r
196 // Notify this event\r
197 //\r
198 ASSERT (Event->NotifyFunction != NULL);\r
199 Event->NotifyFunction (Event, Event->NotifyContext);\r
200\r
201 //\r
202 // Check for next pending event\r
203 //\r
204 CoreAcquireEventLock ();\r
205 }\r
206\r
6e1e5405 207 gEventPending &= ~(UINTN)(1 << Priority);\r
28a00297 208 CoreReleaseEventLock ();\r
209}\r
210\r
211\r
162ed594 212\r
213/**\r
214 Queues the event's notification function to fire.\r
215\r
216 @param Event The Event to notify\r
217\r
218**/\r
28a00297 219VOID\r
220CoreNotifyEvent (\r
221 IN IEVENT *Event\r
222 )\r
28a00297 223{\r
224\r
225 //\r
226 // Event database must be locked\r
227 //\r
228 ASSERT_LOCKED (&gEventQueueLock);\r
229\r
230 //\r
231 // If the event is queued somewhere, remove it\r
232 //\r
233\r
234 if (Event->NotifyLink.ForwardLink != NULL) {\r
235 RemoveEntryList (&Event->NotifyLink);\r
236 Event->NotifyLink.ForwardLink = NULL;\r
237 }\r
238\r
239 //\r
240 // Queue the event to the pending notification list\r
241 //\r
242\r
243 InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);\r
244 gEventPending |= (UINTN)(1 << Event->NotifyTpl);\r
245}\r
246\r
247\r
248\r
162ed594 249\r
250/**\r
251 Signals all events in the EventGroup.\r
252\r
253 @param EventGroup The list to signal\r
254\r
255**/\r
28a00297 256VOID\r
257CoreNotifySignalList (\r
258 IN EFI_GUID *EventGroup\r
259 )\r
28a00297 260{\r
261 LIST_ENTRY *Link;\r
262 LIST_ENTRY *Head;\r
263 IEVENT *Event;\r
264\r
265 CoreAcquireEventLock ();\r
266\r
267 Head = &gEventSignalQueue;\r
268 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
269 Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);\r
270 if (CompareGuid (&Event->EventGroup, EventGroup)) {\r
271 CoreNotifyEvent (Event);\r
272 }\r
273 }\r
274\r
275 CoreReleaseEventLock ();\r
276}\r
277\r
162ed594 278\r
279/**\r
670d4d88 280 Creates an event.\r
162ed594 281\r
022c6d45 282 @param Type The type of event to create and its mode and\r
283 attributes\r
284 @param NotifyTpl The task priority level of event notifications\r
285 @param NotifyFunction Pointer to the events notification function\r
286 @param NotifyContext Pointer to the notification functions context;\r
287 corresponds to parameter "Context" in the\r
288 notification function\r
289 @param Event Pointer to the newly created event if the call\r
290 succeeds; undefined otherwise\r
291\r
292 @retval EFI_SUCCESS The event structure was created\r
293 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
162ed594 294 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
295\r
296**/\r
28a00297 297EFI_STATUS\r
298EFIAPI\r
299CoreCreateEvent (\r
300 IN UINT32 Type,\r
301 IN EFI_TPL NotifyTpl,\r
302 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
303 IN VOID *NotifyContext, OPTIONAL\r
304 OUT EFI_EVENT *Event\r
305 )\r
28a00297 306{\r
bb8ffffd 307 return CoreCreateEventEx (Type, NotifyTpl, NotifyFunction, NotifyContext, NULL, Event);\r
28a00297 308}\r
309\r
310\r
162ed594 311\r
312/**\r
670d4d88 313 Creates an event in a group.\r
162ed594 314\r
022c6d45 315 @param Type The type of event to create and its mode and\r
316 attributes\r
317 @param NotifyTpl The task priority level of event notifications\r
318 @param NotifyFunction Pointer to the events notification function\r
319 @param NotifyContext Pointer to the notification functions context;\r
320 corresponds to parameter "Context" in the\r
321 notification function\r
322 @param EventGroup GUID for EventGroup if NULL act the same as\r
323 gBS->CreateEvent().\r
324 @param Event Pointer to the newly created event if the call\r
325 succeeds; undefined otherwise\r
326\r
327 @retval EFI_SUCCESS The event structure was created\r
328 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
162ed594 329 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
330\r
331**/\r
28a00297 332EFI_STATUS\r
333EFIAPI\r
334CoreCreateEventEx (\r
335 IN UINT32 Type,\r
336 IN EFI_TPL NotifyTpl,\r
337 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
338 IN CONST VOID *NotifyContext, OPTIONAL\r
339 IN CONST EFI_GUID *EventGroup, OPTIONAL\r
340 OUT EFI_EVENT *Event\r
341 )\r
670d4d88
SZ
342{\r
343 //\r
344 // If it's a notify type of event, check for invalid NotifyTpl\r
345 //\r
346 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
347 if (NotifyTpl != TPL_APPLICATION &&\r
348 NotifyTpl != TPL_CALLBACK &&\r
349 NotifyTpl != TPL_NOTIFY) {\r
350 return EFI_INVALID_PARAMETER;\r
351 }\r
352 }\r
353\r
354 return CoreCreateEventInternal (Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, Event);\r
355}\r
356\r
357/**\r
358 Creates a general-purpose event structure\r
359\r
360 @param Type The type of event to create and its mode and\r
361 attributes\r
362 @param NotifyTpl The task priority level of event notifications\r
363 @param NotifyFunction Pointer to the events notification function\r
364 @param NotifyContext Pointer to the notification functions context;\r
365 corresponds to parameter "Context" in the\r
366 notification function\r
367 @param EventGroup GUID for EventGroup if NULL act the same as\r
368 gBS->CreateEvent().\r
369 @param Event Pointer to the newly created event if the call\r
370 succeeds; undefined otherwise\r
371\r
372 @retval EFI_SUCCESS The event structure was created\r
373 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
374 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
375\r
376**/\r
377EFI_STATUS\r
378EFIAPI\r
379CoreCreateEventInternal (\r
380 IN UINT32 Type,\r
381 IN EFI_TPL NotifyTpl,\r
382 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
383 IN CONST VOID *NotifyContext, OPTIONAL\r
384 IN CONST EFI_GUID *EventGroup, OPTIONAL\r
385 OUT EFI_EVENT *Event\r
386 )\r
28a00297 387{\r
388 EFI_STATUS Status;\r
389 IEVENT *IEvent;\r
390 INTN Index;\r
391\r
392\r
51b02d81 393 if (Event == NULL) {\r
28a00297 394 return EFI_INVALID_PARAMETER;\r
395 }\r
396\r
397 //\r
398 // Check to make sure no reserved flags are set\r
399 //\r
400 Status = EFI_INVALID_PARAMETER;\r
401 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {\r
402 if (Type == mEventTable[Index]) {\r
403 Status = EFI_SUCCESS;\r
404 break;\r
405 }\r
406 }\r
407 if(EFI_ERROR (Status)) {\r
408 return EFI_INVALID_PARAMETER;\r
409 }\r
410\r
bb8ffffd 411 //\r
412 // Convert Event type for pre-defined Event groups\r
413 //\r
414 if (EventGroup != NULL) {\r
415 //\r
416 // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE\r
417 // are not valid\r
418 //\r
419 if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {\r
420 return EFI_INVALID_PARAMETER;\r
421 }\r
422 if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {\r
423 Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;\r
424 } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {\r
425 Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;\r
426 }\r
427 } else {\r
428 //\r
429 // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping\r
430 //\r
431 if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {\r
432 EventGroup = &gEfiEventExitBootServicesGuid;\r
433 } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {\r
434 EventGroup = &gEfiEventVirtualAddressChangeGuid;\r
435 }\r
436 }\r
437\r
28a00297 438 //\r
439 // If it's a notify type of event, check its parameters\r
440 //\r
71f68914 441 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
28a00297 442 //\r
443 // Check for an invalid NotifyFunction or NotifyTpl\r
444 //\r
445 if ((NotifyFunction == NULL) ||\r
51b02d81 446 (NotifyTpl <= TPL_APPLICATION) ||\r
28a00297 447 (NotifyTpl >= TPL_HIGH_LEVEL)) {\r
448 return EFI_INVALID_PARAMETER;\r
449 }\r
450\r
451 } else {\r
452 //\r
453 // No notification needed, zero ignored values\r
454 //\r
455 NotifyTpl = 0;\r
456 NotifyFunction = NULL;\r
457 NotifyContext = NULL;\r
458 }\r
459\r
460 //\r
b364eeb0 461 // Allocate and initialize a new event structure.\r
28a00297 462 //\r
b364eeb0 463 if ((Type & EVT_RUNTIME) != 0) {\r
464 IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));\r
465 } else {\r
466 IEvent = AllocateZeroPool (sizeof (IEVENT));\r
467 }\r
468 if (IEvent == NULL) {\r
28a00297 469 return EFI_OUT_OF_RESOURCES;\r
470 }\r
471\r
28a00297 472 IEvent->Signature = EVENT_SIGNATURE;\r
473 IEvent->Type = Type;\r
474\r
475 IEvent->NotifyTpl = NotifyTpl;\r
476 IEvent->NotifyFunction = NotifyFunction;\r
477 IEvent->NotifyContext = (VOID *)NotifyContext;\r
478 if (EventGroup != NULL) {\r
479 CopyGuid (&IEvent->EventGroup, EventGroup);\r
480 IEvent->ExFlag = TRUE;\r
481 }\r
482\r
483 *Event = IEvent;\r
484\r
71f68914 485 if ((Type & EVT_RUNTIME) != 0) {\r
28a00297 486 //\r
487 // Keep a list of all RT events so we can tell the RT AP.\r
488 //\r
489 IEvent->RuntimeData.Type = Type;\r
490 IEvent->RuntimeData.NotifyTpl = NotifyTpl;\r
491 IEvent->RuntimeData.NotifyFunction = NotifyFunction;\r
492 IEvent->RuntimeData.NotifyContext = (VOID *) NotifyContext;\r
493 IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;\r
494 InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);\r
495 }\r
496\r
497 CoreAcquireEventLock ();\r
498\r
499 if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {\r
500 //\r
501 // The Event's NotifyFunction must be queued whenever the event is signaled\r
502 //\r
503 InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);\r
504 }\r
505\r
506 CoreReleaseEventLock ();\r
507\r
508 //\r
509 // Done\r
510 //\r
511 return EFI_SUCCESS;\r
512}\r
513\r
514\r
515\r
28a00297 516\r
162ed594 517/**\r
e94a9ff7 518 Signals the event. Queues the event to be notified if needed.\r
28a00297 519\r
e94a9ff7 520 @param UserEvent The event to signal .\r
28a00297 521\r
022c6d45 522 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 523 @retval EFI_SUCCESS The event was signaled.\r
28a00297 524\r
162ed594 525**/\r
526EFI_STATUS\r
527EFIAPI\r
528CoreSignalEvent (\r
529 IN EFI_EVENT UserEvent\r
530 )\r
28a00297 531{\r
532 IEVENT *Event;\r
533\r
534 Event = UserEvent;\r
535\r
536 if (Event == NULL) {\r
537 return EFI_INVALID_PARAMETER;\r
538 }\r
539\r
540 if (Event->Signature != EVENT_SIGNATURE) {\r
541 return EFI_INVALID_PARAMETER;\r
542 }\r
543\r
544 CoreAcquireEventLock ();\r
545\r
546 //\r
547 // If the event is not already signalled, do so\r
548 //\r
549\r
550 if (Event->SignalCount == 0x00000000) {\r
551 Event->SignalCount++;\r
552\r
553 //\r
554 // If signalling type is a notify function, queue it\r
555 //\r
6e536468 556 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 557 if (Event->ExFlag) {\r
558 //\r
559 // The CreateEventEx() style requires all members of the Event Group\r
560 // to be signaled.\r
561 //\r
562 CoreReleaseEventLock ();\r
563 CoreNotifySignalList (&Event->EventGroup);\r
564 CoreAcquireEventLock ();\r
565 } else {\r
566 CoreNotifyEvent (Event);\r
567 }\r
568 }\r
569 }\r
570\r
571 CoreReleaseEventLock ();\r
572 return EFI_SUCCESS;\r
573}\r
574\r
575\r
162ed594 576\r
577/**\r
578 Check the status of an event.\r
579\r
022c6d45 580 @param UserEvent The event to check\r
162ed594 581\r
022c6d45 582 @retval EFI_SUCCESS The event is in the signaled state\r
583 @retval EFI_NOT_READY The event is not in the signaled state\r
162ed594 584 @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL\r
585\r
586**/\r
28a00297 587EFI_STATUS\r
588EFIAPI\r
589CoreCheckEvent (\r
590 IN EFI_EVENT UserEvent\r
591 )\r
28a00297 592{\r
593 IEVENT *Event;\r
594 EFI_STATUS Status;\r
595\r
596 Event = UserEvent;\r
597\r
598 if (Event == NULL) {\r
599 return EFI_INVALID_PARAMETER;\r
600 }\r
601\r
602 if (Event->Signature != EVENT_SIGNATURE) {\r
603 return EFI_INVALID_PARAMETER;\r
604 }\r
605\r
e94a9ff7 606 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 607 return EFI_INVALID_PARAMETER;\r
608 }\r
609\r
610 Status = EFI_NOT_READY;\r
611\r
6e536468 612 if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {\r
28a00297 613\r
614 //\r
615 // Queue the wait notify function\r
616 //\r
28a00297 617 CoreAcquireEventLock ();\r
6e536468 618 if (Event->SignalCount == 0) {\r
28a00297 619 CoreNotifyEvent (Event);\r
620 }\r
621 CoreReleaseEventLock ();\r
622 }\r
623\r
624 //\r
625 // If the even looks signalled, get the lock and clear it\r
626 //\r
627\r
6e536468 628 if (Event->SignalCount != 0) {\r
28a00297 629 CoreAcquireEventLock ();\r
630\r
6e536468 631 if (Event->SignalCount != 0) {\r
28a00297 632 Event->SignalCount = 0;\r
633 Status = EFI_SUCCESS;\r
634 }\r
635\r
636 CoreReleaseEventLock ();\r
637 }\r
638\r
639 return Status;\r
640}\r
641\r
642\r
643\r
162ed594 644/**\r
645 Stops execution until an event is signaled.\r
646\r
022c6d45 647 @param NumberOfEvents The number of events in the UserEvents array\r
648 @param UserEvents An array of EFI_EVENT\r
649 @param UserIndex Pointer to the index of the event which\r
650 satisfied the wait condition\r
162ed594 651\r
022c6d45 652 @retval EFI_SUCCESS The event indicated by Index was signaled.\r
653 @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification\r
654 function or Event was not a valid type\r
162ed594 655 @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION\r
656\r
657**/\r
28a00297 658EFI_STATUS\r
659EFIAPI\r
660CoreWaitForEvent (\r
661 IN UINTN NumberOfEvents,\r
662 IN EFI_EVENT *UserEvents,\r
663 OUT UINTN *UserIndex\r
664 )\r
28a00297 665{\r
666 EFI_STATUS Status;\r
667 UINTN Index;\r
668\r
669 //\r
670 // Can only WaitForEvent at TPL_APPLICATION\r
671 //\r
672 if (gEfiCurrentTpl != TPL_APPLICATION) {\r
673 return EFI_UNSUPPORTED;\r
674 }\r
675\r
720f84a9
OM
676 if (NumberOfEvents == 0) {\r
677 return EFI_INVALID_PARAMETER;\r
678 }\r
679\r
680 if (UserEvents == NULL) {\r
681 return EFI_INVALID_PARAMETER;\r
682 }\r
683\r
28a00297 684 for(;;) {\r
685\r
686 for(Index = 0; Index < NumberOfEvents; Index++) {\r
687\r
688 Status = CoreCheckEvent (UserEvents[Index]);\r
689\r
690 //\r
691 // provide index of event that caused problem\r
692 //\r
693 if (Status != EFI_NOT_READY) {\r
720f84a9
OM
694 if (UserIndex != NULL) {\r
695 *UserIndex = Index;\r
696 }\r
28a00297 697 return Status;\r
698 }\r
699 }\r
700\r
701 //\r
54cd17e9 702 // Signal the Idle event\r
28a00297 703 //\r
54cd17e9 704 CoreSignalEvent (gIdleLoopEvent);\r
28a00297 705 }\r
706}\r
707\r
708\r
162ed594 709/**\r
28a00297 710 Closes an event and frees the event structure.\r
711\r
022c6d45 712 @param UserEvent Event to close\r
28a00297 713\r
022c6d45 714 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 715 @retval EFI_SUCCESS The event has been closed\r
28a00297 716\r
162ed594 717**/\r
718EFI_STATUS\r
719EFIAPI\r
720CoreCloseEvent (\r
721 IN EFI_EVENT UserEvent\r
722 )\r
28a00297 723{\r
724 EFI_STATUS Status;\r
725 IEVENT *Event;\r
726\r
727 Event = UserEvent;\r
728\r
729 if (Event == NULL) {\r
730 return EFI_INVALID_PARAMETER;\r
731 }\r
732\r
733 if (Event->Signature != EVENT_SIGNATURE) {\r
734 return EFI_INVALID_PARAMETER;\r
735 }\r
736\r
737 //\r
738 // If it's a timer event, make sure it's not pending\r
739 //\r
e94a9ff7 740 if ((Event->Type & EVT_TIMER) != 0) {\r
28a00297 741 CoreSetTimer (Event, TimerCancel, 0);\r
742 }\r
743\r
744 CoreAcquireEventLock ();\r
745\r
746 //\r
747 // If the event is queued somewhere, remove it\r
748 //\r
749\r
750 if (Event->RuntimeData.Link.ForwardLink != NULL) {\r
751 RemoveEntryList (&Event->RuntimeData.Link);\r
752 }\r
753\r
754 if (Event->NotifyLink.ForwardLink != NULL) {\r
755 RemoveEntryList (&Event->NotifyLink);\r
756 }\r
757\r
758 if (Event->SignalLink.ForwardLink != NULL) {\r
759 RemoveEntryList (&Event->SignalLink);\r
760 }\r
761\r
762 CoreReleaseEventLock ();\r
763\r
764 //\r
765 // If the event is registered on a protocol notify, then remove it from the protocol database\r
766 //\r
767 CoreUnregisterProtocolNotify (Event);\r
768\r
769 Status = CoreFreePool (Event);\r
770 ASSERT_EFI_ERROR (Status);\r
771\r
772 return Status;\r
773}\r
54cd17e9 774\r