]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/Dxe/Event/Event.c
MdeModulePkg/Core/Dxe/Gcd: remove set but not used variables
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Event / Event.c
... / ...
CommitLineData
1/** @file\r
2 UEFI Event support functions implemented in this file.\r
3\r
4Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
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
13**/\r
14\r
15\r
16#include "DxeMain.h"\r
17#include "Event.h"\r
18\r
19///\r
20/// gEfiCurrentTpl - Current Task priority level\r
21///\r
22EFI_TPL gEfiCurrentTpl = TPL_APPLICATION;\r
23\r
24///\r
25/// gEventQueueLock - Protects the event queues\r
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
47UINT32 mEventTable[] = {\r
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
52 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
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
57 EVT_TIMER,\r
58 ///\r
59 /// 0x00000100 Generic event with a notification function that\r
60 /// can be waited on with CheckEvent() or WaitForEvent()\r
61 ///\r
62 EVT_NOTIFY_WAIT,\r
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
67 EVT_NOTIFY_SIGNAL,\r
68 ///\r
69 /// 0x00000201 ExitBootServicesEvent.\r
70 ///\r
71 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
72 ///\r
73 /// 0x60000202 SetVirtualAddressMapEvent.\r
74 ///\r
75 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
76\r
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
82 0x00000000,\r
83 ///\r
84 /// 0x80000100 Timer event with a notification function that can be\r
85 /// waited on with CheckEvent() or WaitForEvent()\r
86 ///\r
87 EVT_TIMER | EVT_NOTIFY_WAIT,\r
88};\r
89\r
90///\r
91/// gIdleLoopEvent - Event which is signalled when the core is idle\r
92///\r
93EFI_EVENT gIdleLoopEvent = NULL;\r
94\r
95\r
96/**\r
97 Enter critical section by acquiring the lock on gEventQueueLock.\r
98\r
99**/\r
100VOID\r
101CoreAcquireEventLock (\r
102 VOID\r
103 )\r
104{\r
105 CoreAcquireLock (&gEventQueueLock);\r
106}\r
107\r
108\r
109/**\r
110 Exit critical section by releasing the lock on gEventQueueLock.\r
111\r
112**/\r
113VOID\r
114CoreReleaseEventLock (\r
115 VOID\r
116 )\r
117{\r
118 CoreReleaseLock (&gEventQueueLock);\r
119}\r
120\r
121\r
122\r
123/**\r
124 Initializes "event" support.\r
125\r
126 @retval EFI_SUCCESS Always return success\r
127\r
128**/\r
129EFI_STATUS\r
130CoreInitializeEventServices (\r
131 VOID\r
132 )\r
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
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
151 return EFI_SUCCESS;\r
152}\r
153\r
154\r
155\r
156/**\r
157 Dispatches all pending events.\r
158\r
159 @param Priority The task priority level of event notifications\r
160 to dispatch\r
161\r
162**/\r
163VOID\r
164CoreDispatchEventNotifies (\r
165 IN EFI_TPL Priority\r
166 )\r
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
189 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
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
207 gEventPending &= ~(UINTN)(1 << Priority);\r
208 CoreReleaseEventLock ();\r
209}\r
210\r
211\r
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
219VOID\r
220CoreNotifyEvent (\r
221 IN IEVENT *Event\r
222 )\r
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
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
256VOID\r
257CoreNotifySignalList (\r
258 IN EFI_GUID *EventGroup\r
259 )\r
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
278\r
279/**\r
280 Creates an event.\r
281\r
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
294 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
295\r
296**/\r
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
306{\r
307 return CoreCreateEventEx (Type, NotifyTpl, NotifyFunction, NotifyContext, NULL, Event);\r
308}\r
309\r
310\r
311\r
312/**\r
313 Creates an event in a group.\r
314\r
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
329 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
330\r
331**/\r
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
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
387{\r
388 EFI_STATUS Status;\r
389 IEVENT *IEvent;\r
390 INTN Index;\r
391\r
392\r
393 if (Event == NULL) {\r
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
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
438 //\r
439 // If it's a notify type of event, check its parameters\r
440 //\r
441 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
442 //\r
443 // Check for an invalid NotifyFunction or NotifyTpl\r
444 //\r
445 if ((NotifyFunction == NULL) ||\r
446 (NotifyTpl <= TPL_APPLICATION) ||\r
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
461 // Allocate and initialize a new event structure.\r
462 //\r
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
469 return EFI_OUT_OF_RESOURCES;\r
470 }\r
471\r
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
485 if ((Type & EVT_RUNTIME) != 0) {\r
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
516\r
517/**\r
518 Signals the event. Queues the event to be notified if needed.\r
519\r
520 @param UserEvent The event to signal .\r
521\r
522 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
523 @retval EFI_SUCCESS The event was signaled.\r
524\r
525**/\r
526EFI_STATUS\r
527EFIAPI\r
528CoreSignalEvent (\r
529 IN EFI_EVENT UserEvent\r
530 )\r
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
556 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
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
576\r
577/**\r
578 Check the status of an event.\r
579\r
580 @param UserEvent The event to check\r
581\r
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
584 @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL\r
585\r
586**/\r
587EFI_STATUS\r
588EFIAPI\r
589CoreCheckEvent (\r
590 IN EFI_EVENT UserEvent\r
591 )\r
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
606 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
607 return EFI_INVALID_PARAMETER;\r
608 }\r
609\r
610 Status = EFI_NOT_READY;\r
611\r
612 if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {\r
613\r
614 //\r
615 // Queue the wait notify function\r
616 //\r
617 CoreAcquireEventLock ();\r
618 if (Event->SignalCount == 0) {\r
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
628 if (Event->SignalCount != 0) {\r
629 CoreAcquireEventLock ();\r
630\r
631 if (Event->SignalCount != 0) {\r
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
644/**\r
645 Stops execution until an event is signaled.\r
646\r
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
651\r
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
655 @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION\r
656\r
657**/\r
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
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
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
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
694 if (UserIndex != NULL) {\r
695 *UserIndex = Index;\r
696 }\r
697 return Status;\r
698 }\r
699 }\r
700\r
701 //\r
702 // Signal the Idle event\r
703 //\r
704 CoreSignalEvent (gIdleLoopEvent);\r
705 }\r
706}\r
707\r
708\r
709/**\r
710 Closes an event and frees the event structure.\r
711\r
712 @param UserEvent Event to close\r
713\r
714 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
715 @retval EFI_SUCCESS The event has been closed\r
716\r
717**/\r
718EFI_STATUS\r
719EFIAPI\r
720CoreCloseEvent (\r
721 IN EFI_EVENT UserEvent\r
722 )\r
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
740 if ((Event->Type & EVT_TIMER) != 0) {\r
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
774\r