]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/Dxe/Event/event.c
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@149 6f19259b...
[mirror_edk2.git] / EdkModulePkg / Core / Dxe / Event / event.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 event.c\r
15\r
16Abstract:\r
17\r
18 EFI Event support\r
19 \r
20--*/\r
21\r
22\r
23#include <DxeMain.h>\r
24\r
25//\r
26// Enumerate the valid types\r
27//\r
28UINT32 mEventTable[] = {\r
29 //\r
30 // 0x80000200 Timer event with a notification function that is\r
31 // queue when the event is signaled with SignalEvent()\r
32 //\r
33 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
34 //\r
35 // 0x80000000 Timer event without a notification function. It can be\r
36 // signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().\r
37 //\r
38 EFI_EVENT_TIMER,\r
39 //\r
40 // 0x00000100 Generic event with a notification function that \r
41 // can be waited on with CheckEvent() or WaitForEvent()\r
42 //\r
43 EFI_EVENT_NOTIFY_WAIT,\r
44 //\r
45 // 0x00000200 Generic event with a notification function that \r
46 // is queue when the event is signaled with SignalEvent()\r
47 //\r
48 EFI_EVENT_NOTIFY_SIGNAL,\r
49 //\r
50 // 0x00000201 ExitBootServicesEvent. \r
51 //\r
52 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,\r
53 //\r
54 // 0x60000202 SetVirtualAddressMapEvent.\r
55 //\r
56 EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
57\r
58#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
59 //\r
60 // 0x00000203 ReadyToBootEvent.\r
61 //\r
62 EFI_EVENT_SIGNAL_READY_TO_BOOT,\r
63 //\r
64 // 0x00000204 LegacyBootEvent.\r
65 //\r
66 EFI_EVENT_SIGNAL_LEGACY_BOOT,\r
67 //\r
68 // 0x00000603 Signal all ReadyToBootEvents.\r
69 //\r
70 EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_READY_TO_BOOT,\r
71 //\r
72 // 0x00000604 Signal all LegacyBootEvents.\r
73 //\r
74 EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_LEGACY_BOOT,\r
75#endif\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 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_WAIT,\r
88};\r
89\r
90\r
91VOID\r
92CoreAcquireEventLock (\r
93 VOID\r
94 )\r
95/*++\r
96\r
97Routine Description:\r
98\r
99 Enter critical section by acquiring the lock on gEventQueueLock.\r
100\r
101Arguments:\r
102\r
103 None\r
104\r
105Returns:\r
106\r
107 None\r
108\r
109--*/\r
110{\r
111 CoreAcquireLock (&gEventQueueLock);\r
112}\r
113\r
114\r
115VOID\r
116CoreReleaseEventLock (\r
117 VOID\r
118 )\r
119/*++\r
120\r
121Routine Description:\r
122\r
123 Exit critical section by releasing the lock on gEventQueueLock.\r
124\r
125Arguments:\r
126\r
127 None\r
128\r
129Returns:\r
130\r
131 None\r
132\r
133--*/\r
134{\r
135 CoreReleaseLock (&gEventQueueLock);\r
136}\r
137\r
138\r
139EFI_STATUS\r
140CoreInitializeEventServices (\r
141 VOID\r
142 )\r
143/*++\r
144\r
145Routine Description:\r
146\r
147 Initializes "event" support and populates parts of the System and Runtime Table.\r
148\r
149Arguments:\r
150\r
151 None\r
152 \r
153Returns:\r
154\r
155 EFI_SUCCESS - Always return success\r
156\r
157--*/\r
158{\r
159 UINTN Index;\r
160\r
161 for (Index=0; Index <= EFI_TPL_HIGH_LEVEL; Index++) {\r
162 InitializeListHead (&gEventQueue[Index]);\r
163 }\r
164\r
165 CoreInitializeTimer ();\r
166 \r
167 return EFI_SUCCESS;\r
168}\r
169\r
170\r
171EFI_STATUS\r
172CoreShutdownEventServices (\r
173 VOID\r
174 )\r
175/*++\r
176\r
177Routine Description:\r
178\r
179 Register all runtime events to make sure they are still available after ExitBootService.\r
180\r
181Arguments:\r
182\r
183 None\r
184 \r
185Returns:\r
186\r
187 EFI_SUCCESS - Always return success.\r
188\r
189--*/\r
190{\r
191 LIST_ENTRY *Link;\r
192 IEVENT *Event;\r
193\r
194 //\r
195 // The Runtime AP is required for the core to function!\r
196 //\r
197 ASSERT (gRuntime != NULL);\r
198\r
199 for (Link = mRuntimeEventList.ForwardLink; Link != &mRuntimeEventList; Link = Link->ForwardLink) {\r
200 Event = CR (Link, IEVENT, RuntimeLink, EVENT_SIGNATURE);\r
201 gRuntime->RegisterEvent (\r
202 gRuntime, \r
203 Event->Type, \r
204 Event->NotifyTpl, \r
205 Event->NotifyFunction, \r
206 Event->NotifyContext, \r
207 (VOID **)Event\r
208 );\r
209 }\r
210\r
211 return EFI_SUCCESS;\r
212}\r
213\r
214\r
215VOID\r
216CoreDispatchEventNotifies (\r
217 IN EFI_TPL Priority\r
218 )\r
219/*++\r
220\r
221Routine Description:\r
222\r
223 Dispatches all pending events. \r
224\r
225Arguments:\r
226\r
227 Priority - The task priority level of event notifications to dispatch\r
228 \r
229Returns:\r
230\r
231 None\r
232\r
233--*/\r
234{\r
235 IEVENT *Event;\r
236 LIST_ENTRY *Head;\r
237 \r
238 CoreAcquireEventLock ();\r
239 ASSERT (gEventQueueLock.OwnerTpl == Priority);\r
240 Head = &gEventQueue[Priority];\r
241\r
242 //\r
243 // Dispatch all the pending notifications\r
244 //\r
245 while (!IsListEmpty (Head)) {\r
246 \r
247 Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);\r
248 RemoveEntryList (&Event->NotifyLink);\r
249\r
250 Event->NotifyLink.ForwardLink = NULL;\r
251\r
252 //\r
253 // Only clear the SIGNAL status if it is a SIGNAL type event.\r
254 // WAIT type events are only cleared in CheckEvent()\r
255 //\r
256 if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {\r
257 Event->SignalCount = 0;\r
258 }\r
259\r
260 CoreReleaseEventLock ();\r
261 \r
262 //\r
263 // Notify this event\r
264 //\r
265 ASSERT (Event->NotifyFunction != NULL);\r
266 Event->NotifyFunction (Event, Event->NotifyContext);\r
267\r
268 //\r
269 // Check for next pending event\r
270 //\r
271 CoreAcquireEventLock ();\r
272 }\r
273\r
274 gEventPending &= ~(1 << Priority);\r
275 CoreReleaseEventLock ();\r
276}\r
277\r
278\r
279VOID\r
280STATIC\r
281CoreNotifyEvent (\r
282 IN IEVENT *Event\r
283 )\r
284/*++\r
285\r
286Routine Description:\r
287\r
288 Queues the event's notification function to fire\r
289\r
290Arguments:\r
291\r
292 Event - The Event to notify\r
293 \r
294Returns:\r
295\r
296 None\r
297\r
298--*/\r
299{\r
300\r
301 //\r
302 // Event database must be locked\r
303 //\r
304 ASSERT_LOCKED (&gEventQueueLock);\r
305\r
306 //\r
307 // If the event is queued somewhere, remove it\r
308 //\r
309\r
310 if (Event->NotifyLink.ForwardLink != NULL) {\r
311 RemoveEntryList (&Event->NotifyLink);\r
312 Event->NotifyLink.ForwardLink = NULL;\r
313 }\r
314\r
315 // \r
316 // Queue the event to the pending notification list\r
317 //\r
318\r
319 InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);\r
320 gEventPending |= (UINTN)(1 << Event->NotifyTpl);\r
321}\r
322\r
323\r
324\r
325VOID\r
326CoreNotifySignalList (\r
327 IN EFI_GUID *EventGroup\r
328 )\r
329/*++\r
330\r
331Routine Description:\r
332 Signals all events in the EventGroup\r
333\r
334Arguments:\r
335 EventGroup - The list to signal\r
336 \r
337Returns:\r
338\r
339 None\r
340\r
341--*/\r
342{\r
343 LIST_ENTRY *Link;\r
344 LIST_ENTRY *Head;\r
345 IEVENT *Event;\r
346\r
347 CoreAcquireEventLock ();\r
348\r
349 Head = &gEventSignalQueue;\r
350 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
351 Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);\r
352 if (CompareGuid (&Event->EventGroup, EventGroup)) {\r
353 CoreNotifyEvent (Event);\r
354 }\r
355 }\r
356\r
357 CoreReleaseEventLock ();\r
358}\r
359\r
360\r
361#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
362\r
363static\r
364VOID\r
365EFIAPI\r
366EventNofitySignalAllNullEvent (\r
367 IN EFI_EVENT Event,\r
368 IN VOID *Context\r
369 )\r
370{\r
371 //\r
372 // This null event is a size efficent way to enusre that \r
373 // EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.\r
374 // EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into \r
375 // CreateEventEx() and this function is used to make the\r
376 // old error checking in CreateEvent() for Tiano extensions\r
377 // function.\r
378 //\r
379 return;\r
380}\r
381\r
382#endif\r
383\r
384\r
385\r
386\r
387EFI_STATUS\r
388EFIAPI\r
389CoreCreateEvent (\r
390 IN UINT32 Type,\r
391 IN EFI_TPL NotifyTpl,\r
392 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
393 IN VOID *NotifyContext, OPTIONAL\r
394 OUT EFI_EVENT *Event\r
395 )\r
396/*++\r
397\r
398Routine Description:\r
399 Creates a general-purpose event structure\r
400\r
401Arguments:\r
402 Type - The type of event to create and its mode and attributes\r
403 NotifyTpl - The task priority level of event notifications\r
404 NotifyFunction - Pointer to the events notification function\r
405 NotifyContext - Pointer to the notification functions context; corresponds to\r
406 parameter "Context" in the notification function\r
407 Event - Pointer to the newly created event if the call succeeds; undefined otherwise\r
408\r
409Returns:\r
410 EFI_SUCCESS - The event structure was created\r
411 EFI_INVALID_PARAMETER - One of the parameters has an invalid value\r
412 EFI_OUT_OF_RESOURCES - The event could not be allocated\r
413\r
414--*/\r
415{ \r
416 EFI_GUID *GuidPtr;\r
417 EFI_EVENT_NOTIFY Function;\r
418 \r
419 GuidPtr = NULL;\r
420 Function = NotifyFunction;\r
421\r
422#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
423 //\r
424 // Clear EFI_EVENT_NOFITY_SIGNAL_ALL (Tiano extension) as all events in the \r
425 // EventGroup now have this property. So we need to filter it out.\r
426 //\r
427 if (Type & EFI_EVENT_NOTIFY_SIGNAL_ALL) {\r
428 Type &= ~EFI_EVENT_NOTIFY_SIGNAL_ALL;\r
429 Function = EventNofitySignalAllNullEvent;\r
430 }\r
431\r
432 //\r
433 // Map the Tiano extensions Events to CreateEventEx form\r
434 //\r
435 if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) {\r
436 GuidPtr = &gEfiEventReadToBootGuid;\r
437 } else if (Type == EFI_EVENT_SIGNAL_LEGACY_BOOT) {\r
438 GuidPtr = &gEfiEventLegacyBootGuid\r
439 }\r
440#endif\r
441\r
442 //\r
443 // Convert EFI 1.10 Events to thier UEFI 2.0 CreateEventEx mapping\r
444 // \r
445 if (Type == EVENT_SIGNAL_EXIT_BOOT_SERVICES) {\r
446 GuidPtr = &gEfiEventExitBootServicesGuid;\r
447 } else if (Type == EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {\r
448 GuidPtr = &gEfiEventVirtualAddressChangeGuid;\r
449 }\r
450 \r
451 return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event);\r
452}\r
453\r
454\r
455EFI_STATUS\r
456EFIAPI\r
457CoreCreateEventEx (\r
458 IN UINT32 Type,\r
459 IN EFI_TPL NotifyTpl,\r
460 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
461 IN CONST VOID *NotifyContext, OPTIONAL\r
462 IN CONST EFI_GUID *EventGroup, OPTIONAL\r
463 OUT EFI_EVENT *Event\r
464 )\r
465/*++\r
466\r
467Routine Description:\r
468 Creates a general-purpose event structure\r
469\r
470Arguments:\r
471 Type - The type of event to create and its mode and attributes\r
472 NotifyTpl - The task priority level of event notifications\r
473 NotifyFunction - Pointer to the events notification function\r
474 NotifyContext - Pointer to the notification functions context; corresponds to\r
475 parameter "Context" in the notification function\r
476 EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent().\r
477 Event - Pointer to the newly created event if the call succeeds; undefined otherwise\r
478\r
479Returns:\r
480 EFI_SUCCESS - The event structure was created\r
481 EFI_INVALID_PARAMETER - One of the parameters has an invalid value\r
482 EFI_OUT_OF_RESOURCES - The event could not be allocated\r
483\r
484--*/\r
485{\r
486 EFI_STATUS Status;\r
487 IEVENT *IEvent;\r
488 INTN Index;\r
489\r
490\r
491 if ((Event == NULL) || (NotifyTpl == EFI_TPL_APPLICATION)) {\r
492 return EFI_INVALID_PARAMETER;\r
493 }\r
494\r
495 //\r
496 // Check to make sure no reserved flags are set\r
497 //\r
498 Status = EFI_INVALID_PARAMETER;\r
499 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {\r
500 if (Type == mEventTable[Index]) {\r
501 Status = EFI_SUCCESS;\r
502 break;\r
503 }\r
504 }\r
505 if(EFI_ERROR (Status)) {\r
506 return EFI_INVALID_PARAMETER;\r
507 }\r
508\r
509 //\r
510 // If it's a notify type of event, check its parameters\r
511 //\r
512 if ((Type & (EFI_EVENT_NOTIFY_WAIT | EFI_EVENT_NOTIFY_SIGNAL))) {\r
513 //\r
514 // Check for an invalid NotifyFunction or NotifyTpl\r
515 //\r
516 if ((NotifyFunction == NULL) || \r
517 (NotifyTpl < EFI_TPL_APPLICATION) || \r
518 (NotifyTpl >= EFI_TPL_HIGH_LEVEL)) {\r
519 return EFI_INVALID_PARAMETER;\r
520 }\r
521\r
522 } else {\r
523 //\r
524 // No notification needed, zero ignored values\r
525 //\r
526 NotifyTpl = 0;\r
527 NotifyFunction = NULL;\r
528 NotifyContext = NULL;\r
529 }\r
530\r
531 //\r
532 // Allcoate and initialize a new event structure.\r
533 //\r
534 Status = CoreAllocatePool (\r
535 (Type & EFI_EVENT_RUNTIME) ? EfiRuntimeServicesData: EfiBootServicesData, \r
536 sizeof (IEVENT),\r
537 (VOID **)&IEvent\r
538 );\r
539 if (EFI_ERROR (Status)) {\r
540 return EFI_OUT_OF_RESOURCES;\r
541 }\r
542\r
543 SetMem (IEvent, sizeof (IEVENT), 0);\r
544\r
545 IEvent->Signature = EVENT_SIGNATURE;\r
546 IEvent->Type = Type;\r
547 \r
548 IEvent->NotifyTpl = NotifyTpl;\r
549 IEvent->NotifyFunction = NotifyFunction;\r
550 IEvent->NotifyContext = (VOID *)NotifyContext;\r
551 if (EventGroup != NULL) {\r
552 CopyGuid (&IEvent->EventGroup, EventGroup);\r
553 IEvent->ExFlag = TRUE;\r
554 }\r
555\r
556 *Event = IEvent;\r
557\r
558 if (Type & EFI_EVENT_RUNTIME) {\r
559 //\r
560 // Keep a list of all RT events so we can tell the RT AP.\r
561 //\r
562 InsertTailList (&mRuntimeEventList, &IEvent->RuntimeLink);\r
563 }\r
564\r
565 CoreAcquireEventLock ();\r
566 \r
567 if ((Type & EFI_EVENT_NOTIFY_SIGNAL) != 0x00000000) {\r
568 //\r
569 // The Event's NotifyFunction must be queued whenever the event is signaled\r
570 //\r
571 InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);\r
572 }\r
573 \r
574 CoreReleaseEventLock ();\r
575 \r
576 //\r
577 // Done\r
578 //\r
579 return EFI_SUCCESS;\r
580}\r
581\r
582\r
583\r
584EFI_STATUS\r
585EFIAPI\r
586CoreSignalEvent (\r
587 IN EFI_EVENT UserEvent\r
588 )\r
589/*++\r
590\r
591Routine Description:\r
592\r
593 Signals the event. Queues the event to be notified if needed\r
594 \r
595Arguments:\r
596\r
597 UserEvent - The event to signal\r
598 \r
599Returns:\r
600\r
601 EFI_INVALID_PARAMETER - Parameters are not valid.\r
602 \r
603 EFI_SUCCESS - The event was signaled.\r
604\r
605--*/\r
606{\r
607 IEVENT *Event;\r
608\r
609 Event = UserEvent;\r
610\r
611 if (Event == NULL) {\r
612 return EFI_INVALID_PARAMETER;\r
613 }\r
614\r
615 if (Event->Signature != EVENT_SIGNATURE) {\r
616 return EFI_INVALID_PARAMETER;\r
617 }\r
618\r
619 CoreAcquireEventLock ();\r
620\r
621 //\r
622 // If the event is not already signalled, do so\r
623 //\r
624\r
625 if (Event->SignalCount == 0x00000000) {\r
626 Event->SignalCount++;\r
627\r
628 //\r
629 // If signalling type is a notify function, queue it\r
630 //\r
631 if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {\r
632 if (Event->ExFlag) {\r
633 //\r
634 // The CreateEventEx() style requires all members of the Event Group \r
635 // to be signaled. \r
636 //\r
637 CoreReleaseEventLock ();\r
638 CoreNotifySignalList (&Event->EventGroup);\r
639 CoreAcquireEventLock ();\r
640 } else {\r
641 CoreNotifyEvent (Event);\r
642 }\r
643 }\r
644 }\r
645\r
646 CoreReleaseEventLock ();\r
647 return EFI_SUCCESS;\r
648}\r
649\r
650\r
651EFI_STATUS\r
652EFIAPI\r
653CoreCheckEvent (\r
654 IN EFI_EVENT UserEvent\r
655 )\r
656/*++\r
657\r
658Routine Description:\r
659\r
660 Check the status of an event\r
661 \r
662Arguments:\r
663\r
664 UserEvent - The event to check\r
665 \r
666Returns:\r
667\r
668 EFI_SUCCESS - The event is in the signaled state\r
669 EFI_NOT_READY - The event is not in the signaled state\r
670 EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL\r
671\r
672--*/\r
673\r
674{\r
675 IEVENT *Event;\r
676 EFI_STATUS Status;\r
677\r
678 Event = UserEvent;\r
679\r
680 if (Event == NULL) {\r
681 return EFI_INVALID_PARAMETER;\r
682 }\r
683\r
684 if (Event->Signature != EVENT_SIGNATURE) {\r
685 return EFI_INVALID_PARAMETER;\r
686 }\r
687\r
688 if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {\r
689 return EFI_INVALID_PARAMETER;\r
690 }\r
691\r
692 Status = EFI_NOT_READY;\r
693\r
694 if (!Event->SignalCount && (Event->Type & EFI_EVENT_NOTIFY_WAIT)) {\r
695\r
696 //\r
697 // Queue the wait notify function\r
698 //\r
699\r
700 CoreAcquireEventLock ();\r
701 if (!Event->SignalCount) {\r
702 CoreNotifyEvent (Event);\r
703 }\r
704 CoreReleaseEventLock ();\r
705 }\r
706\r
707 //\r
708 // If the even looks signalled, get the lock and clear it\r
709 //\r
710\r
711 if (Event->SignalCount) {\r
712 CoreAcquireEventLock ();\r
713\r
714 if (Event->SignalCount) {\r
715 Event->SignalCount = 0;\r
716 Status = EFI_SUCCESS;\r
717 }\r
718\r
719 CoreReleaseEventLock ();\r
720 }\r
721\r
722 return Status;\r
723}\r
724\r
725\r
726\r
727EFI_STATUS\r
728EFIAPI\r
729CoreWaitForEvent (\r
730 IN UINTN NumberOfEvents,\r
731 IN EFI_EVENT *UserEvents,\r
732 OUT UINTN *UserIndex\r
733 )\r
734/*++\r
735\r
736Routine Description:\r
737\r
738 Stops execution until an event is signaled.\r
739 \r
740Arguments:\r
741\r
742 NumberOfEvents - The number of events in the UserEvents array\r
743 UserEvents - An array of EFI_EVENT\r
744 UserIndex - Pointer to the index of the event which satisfied the wait condition\r
745 \r
746Returns:\r
747\r
748 EFI_SUCCESS - The event indicated by Index was signaled.\r
749 EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or \r
750 Event was not a valid type\r
751 EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION\r
752\r
753--*/\r
754\r
755{\r
756 EFI_STATUS Status;\r
757 UINTN Index;\r
758\r
759 //\r
760 // Can only WaitForEvent at TPL_APPLICATION\r
761 //\r
762 if (gEfiCurrentTpl != EFI_TPL_APPLICATION) {\r
763 return EFI_UNSUPPORTED;\r
764 }\r
765\r
766 for(;;) {\r
767 \r
768 for(Index = 0; Index < NumberOfEvents; Index++) {\r
769\r
770 Status = CoreCheckEvent (UserEvents[Index]);\r
771\r
772 //\r
773 // provide index of event that caused problem\r
774 //\r
775 if (Status != EFI_NOT_READY) {\r
776 *UserIndex = Index;\r
777 return Status;\r
778 }\r
779 }\r
780\r
781 //\r
782 // This was the location of the Idle loop callback in EFI 1.x reference\r
783 // code. We don't have that concept in this base at this point.\r
784 // \r
785 }\r
786}\r
787\r
788\r
789EFI_STATUS\r
790EFIAPI\r
791CoreCloseEvent (\r
792 IN EFI_EVENT UserEvent\r
793 )\r
794/*++\r
795\r
796Routine Description:\r
797\r
798 Closes an event and frees the event structure.\r
799 \r
800Arguments:\r
801\r
802 UserEvent - Event to close\r
803 \r
804Returns:\r
805\r
806 EFI_INVALID_PARAMETER - Parameters are not valid.\r
807 \r
808 EFI_SUCCESS - The event has been closed\r
809\r
810--*/\r
811\r
812{\r
813 EFI_STATUS Status;\r
814 IEVENT *Event;\r
815\r
816 Event = UserEvent;\r
817\r
818 if (Event == NULL) {\r
819 return EFI_INVALID_PARAMETER;\r
820 }\r
821\r
822 if (Event->Signature != EVENT_SIGNATURE) {\r
823 return EFI_INVALID_PARAMETER;\r
824 }\r
825\r
826 //\r
827 // If it's a timer event, make sure it's not pending\r
828 //\r
829 if (Event->Type & EFI_EVENT_TIMER) {\r
830 CoreSetTimer (Event, TimerCancel, 0);\r
831 }\r
832\r
833 CoreAcquireEventLock ();\r
834\r
835 //\r
836 // If the event is queued somewhere, remove it\r
837 //\r
838\r
839 if (Event->RuntimeLink.ForwardLink != NULL) {\r
840 RemoveEntryList (&Event->RuntimeLink);\r
841 }\r
842\r
843 if (Event->NotifyLink.ForwardLink != NULL) {\r
844 RemoveEntryList (&Event->NotifyLink);\r
845 }\r
846\r
847 if (Event->SignalLink.ForwardLink != NULL) {\r
848 RemoveEntryList (&Event->SignalLink);\r
849 }\r
850\r
851 CoreReleaseEventLock ();\r
852\r
853 //\r
854 // If the event is registered on a protocol notify, then remove it from the protocol database\r
855 //\r
856 CoreUnregisterProtocolNotify (Event);\r
857\r
858 Status = CoreFreePool (Event);\r
859 ASSERT_EFI_ERROR (Status);\r
860\r
861 return Status;\r
862}\r