]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/Dxe/Event/event.c
Change the TPL lock level to EFI_TPL_NOTIFY. Variable Service is called in ResetSyste...
[mirror_edk2.git] / EdkModulePkg / Core / Dxe / Event / event.c
CommitLineData
6652e7be 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
1cc8ee78 90STATIC\r
6652e7be 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
1cc8ee78 114STATIC\r
6652e7be 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
6652e7be 171VOID\r
172CoreDispatchEventNotifies (\r
173 IN EFI_TPL Priority\r
174 )\r
175/*++\r
176\r
177Routine Description:\r
178\r
179 Dispatches all pending events. \r
180\r
181Arguments:\r
182\r
183 Priority - The task priority level of event notifications to dispatch\r
184 \r
185Returns:\r
186\r
187 None\r
188\r
189--*/\r
190{\r
191 IEVENT *Event;\r
192 LIST_ENTRY *Head;\r
193 \r
194 CoreAcquireEventLock ();\r
195 ASSERT (gEventQueueLock.OwnerTpl == Priority);\r
196 Head = &gEventQueue[Priority];\r
197\r
198 //\r
199 // Dispatch all the pending notifications\r
200 //\r
201 while (!IsListEmpty (Head)) {\r
202 \r
203 Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);\r
204 RemoveEntryList (&Event->NotifyLink);\r
205\r
206 Event->NotifyLink.ForwardLink = NULL;\r
207\r
208 //\r
209 // Only clear the SIGNAL status if it is a SIGNAL type event.\r
210 // WAIT type events are only cleared in CheckEvent()\r
211 //\r
212 if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {\r
213 Event->SignalCount = 0;\r
214 }\r
215\r
216 CoreReleaseEventLock ();\r
217 \r
218 //\r
219 // Notify this event\r
220 //\r
221 ASSERT (Event->NotifyFunction != NULL);\r
222 Event->NotifyFunction (Event, Event->NotifyContext);\r
223\r
224 //\r
225 // Check for next pending event\r
226 //\r
227 CoreAcquireEventLock ();\r
228 }\r
229\r
230 gEventPending &= ~(1 << Priority);\r
231 CoreReleaseEventLock ();\r
232}\r
233\r
234\r
6652e7be 235STATIC\r
1cc8ee78 236VOID\r
6652e7be 237CoreNotifyEvent (\r
238 IN IEVENT *Event\r
239 )\r
240/*++\r
241\r
242Routine Description:\r
243\r
244 Queues the event's notification function to fire\r
245\r
246Arguments:\r
247\r
248 Event - The Event to notify\r
249 \r
250Returns:\r
251\r
252 None\r
253\r
254--*/\r
255{\r
256\r
257 //\r
258 // Event database must be locked\r
259 //\r
260 ASSERT_LOCKED (&gEventQueueLock);\r
261\r
262 //\r
263 // If the event is queued somewhere, remove it\r
264 //\r
265\r
266 if (Event->NotifyLink.ForwardLink != NULL) {\r
267 RemoveEntryList (&Event->NotifyLink);\r
268 Event->NotifyLink.ForwardLink = NULL;\r
269 }\r
270\r
271 // \r
272 // Queue the event to the pending notification list\r
273 //\r
274\r
275 InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);\r
276 gEventPending |= (UINTN)(1 << Event->NotifyTpl);\r
277}\r
278\r
279\r
280\r
281VOID\r
282CoreNotifySignalList (\r
283 IN EFI_GUID *EventGroup\r
284 )\r
285/*++\r
286\r
287Routine Description:\r
288 Signals all events in the EventGroup\r
289\r
290Arguments:\r
291 EventGroup - The list to signal\r
292 \r
293Returns:\r
294\r
295 None\r
296\r
297--*/\r
298{\r
299 LIST_ENTRY *Link;\r
300 LIST_ENTRY *Head;\r
301 IEVENT *Event;\r
302\r
303 CoreAcquireEventLock ();\r
304\r
305 Head = &gEventSignalQueue;\r
306 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
307 Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);\r
308 if (CompareGuid (&Event->EventGroup, EventGroup)) {\r
309 CoreNotifyEvent (Event);\r
310 }\r
311 }\r
312\r
313 CoreReleaseEventLock ();\r
314}\r
315\r
316\r
317#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
318\r
319static\r
320VOID\r
321EFIAPI\r
d4f397c0 322EventNotifySignalAllNullEvent (\r
6652e7be 323 IN EFI_EVENT Event,\r
324 IN VOID *Context\r
325 )\r
326{\r
327 //\r
328 // This null event is a size efficent way to enusre that \r
329 // EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.\r
330 // EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into \r
331 // CreateEventEx() and this function is used to make the\r
332 // old error checking in CreateEvent() for Tiano extensions\r
333 // function.\r
334 //\r
335 return;\r
336}\r
337\r
338#endif\r
339\r
340\r
341\r
342\r
343EFI_STATUS\r
344EFIAPI\r
345CoreCreateEvent (\r
346 IN UINT32 Type,\r
347 IN EFI_TPL NotifyTpl,\r
348 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
349 IN VOID *NotifyContext, OPTIONAL\r
350 OUT EFI_EVENT *Event\r
351 )\r
352/*++\r
353\r
354Routine Description:\r
355 Creates a general-purpose event structure\r
356\r
357Arguments:\r
358 Type - The type of event to create and its mode and attributes\r
359 NotifyTpl - The task priority level of event notifications\r
360 NotifyFunction - Pointer to the events notification function\r
361 NotifyContext - Pointer to the notification functions context; corresponds to\r
362 parameter "Context" in the notification function\r
363 Event - Pointer to the newly created event if the call succeeds; undefined otherwise\r
364\r
365Returns:\r
366 EFI_SUCCESS - The event structure was created\r
367 EFI_INVALID_PARAMETER - One of the parameters has an invalid value\r
368 EFI_OUT_OF_RESOURCES - The event could not be allocated\r
369\r
370--*/\r
371{ \r
372 EFI_GUID *GuidPtr;\r
373 EFI_EVENT_NOTIFY Function;\r
374 \r
375 GuidPtr = NULL;\r
376 Function = NotifyFunction;\r
377\r
378#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
379 //\r
380 // Clear EFI_EVENT_NOFITY_SIGNAL_ALL (Tiano extension) as all events in the \r
381 // EventGroup now have this property. So we need to filter it out.\r
382 //\r
383 if (Type & EFI_EVENT_NOTIFY_SIGNAL_ALL) {\r
384 Type &= ~EFI_EVENT_NOTIFY_SIGNAL_ALL;\r
d4f397c0 385 Function = EventNotifySignalAllNullEvent;\r
6652e7be 386 }\r
387\r
388 //\r
389 // Map the Tiano extensions Events to CreateEventEx form\r
390 //\r
391 if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) {\r
392 GuidPtr = &gEfiEventReadyToBootGuid;\r
393 } else if (Type == EFI_EVENT_SIGNAL_LEGACY_BOOT) {\r
394 GuidPtr = &gEfiEventLegacyBootGuid\r
395 }\r
396#endif\r
397\r
398 //\r
399 // Convert EFI 1.10 Events to thier UEFI 2.0 CreateEventEx mapping\r
400 // \r
401 if (Type == EVENT_SIGNAL_EXIT_BOOT_SERVICES) {\r
402 GuidPtr = &gEfiEventExitBootServicesGuid;\r
403 } else if (Type == EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {\r
404 GuidPtr = &gEfiEventVirtualAddressChangeGuid;\r
405 }\r
406 \r
407 return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event);\r
408}\r
409\r
410\r
411EFI_STATUS\r
412EFIAPI\r
413CoreCreateEventEx (\r
414 IN UINT32 Type,\r
415 IN EFI_TPL NotifyTpl,\r
416 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
417 IN CONST VOID *NotifyContext, OPTIONAL\r
418 IN CONST EFI_GUID *EventGroup, OPTIONAL\r
419 OUT EFI_EVENT *Event\r
420 )\r
421/*++\r
422\r
423Routine Description:\r
424 Creates a general-purpose event structure\r
425\r
426Arguments:\r
427 Type - The type of event to create and its mode and attributes\r
428 NotifyTpl - The task priority level of event notifications\r
429 NotifyFunction - Pointer to the events notification function\r
430 NotifyContext - Pointer to the notification functions context; corresponds to\r
431 parameter "Context" in the notification function\r
432 EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent().\r
433 Event - Pointer to the newly created event if the call succeeds; undefined otherwise\r
434\r
435Returns:\r
436 EFI_SUCCESS - The event structure was created\r
437 EFI_INVALID_PARAMETER - One of the parameters has an invalid value\r
438 EFI_OUT_OF_RESOURCES - The event could not be allocated\r
439\r
440--*/\r
441{\r
442 EFI_STATUS Status;\r
443 IEVENT *IEvent;\r
444 INTN Index;\r
445\r
446\r
447 if ((Event == NULL) || (NotifyTpl == EFI_TPL_APPLICATION)) {\r
448 return EFI_INVALID_PARAMETER;\r
449 }\r
450\r
451 //\r
452 // Check to make sure no reserved flags are set\r
453 //\r
454 Status = EFI_INVALID_PARAMETER;\r
455 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {\r
456 if (Type == mEventTable[Index]) {\r
457 Status = EFI_SUCCESS;\r
458 break;\r
459 }\r
460 }\r
461 if(EFI_ERROR (Status)) {\r
462 return EFI_INVALID_PARAMETER;\r
463 }\r
464\r
465 //\r
466 // If it's a notify type of event, check its parameters\r
467 //\r
468 if ((Type & (EFI_EVENT_NOTIFY_WAIT | EFI_EVENT_NOTIFY_SIGNAL))) {\r
469 //\r
470 // Check for an invalid NotifyFunction or NotifyTpl\r
471 //\r
472 if ((NotifyFunction == NULL) || \r
473 (NotifyTpl < EFI_TPL_APPLICATION) || \r
474 (NotifyTpl >= EFI_TPL_HIGH_LEVEL)) {\r
475 return EFI_INVALID_PARAMETER;\r
476 }\r
477\r
478 } else {\r
479 //\r
480 // No notification needed, zero ignored values\r
481 //\r
482 NotifyTpl = 0;\r
483 NotifyFunction = NULL;\r
484 NotifyContext = NULL;\r
485 }\r
486\r
487 //\r
488 // Allcoate and initialize a new event structure.\r
489 //\r
490 Status = CoreAllocatePool (\r
491 (Type & EFI_EVENT_RUNTIME) ? EfiRuntimeServicesData: EfiBootServicesData, \r
492 sizeof (IEVENT),\r
493 (VOID **)&IEvent\r
494 );\r
495 if (EFI_ERROR (Status)) {\r
496 return EFI_OUT_OF_RESOURCES;\r
497 }\r
498\r
499 SetMem (IEvent, sizeof (IEVENT), 0);\r
500\r
501 IEvent->Signature = EVENT_SIGNATURE;\r
502 IEvent->Type = Type;\r
503 \r
504 IEvent->NotifyTpl = NotifyTpl;\r
505 IEvent->NotifyFunction = NotifyFunction;\r
506 IEvent->NotifyContext = (VOID *)NotifyContext;\r
507 if (EventGroup != NULL) {\r
508 CopyGuid (&IEvent->EventGroup, EventGroup);\r
509 IEvent->ExFlag = TRUE;\r
510 }\r
511\r
512 *Event = IEvent;\r
513\r
514 if (Type & EFI_EVENT_RUNTIME) {\r
515 //\r
516 // Keep a list of all RT events so we can tell the RT AP.\r
517 //\r
3ec2611d
LG
518 IEvent->RuntimeData.Type = Type;\r
519 IEvent->RuntimeData.NotifyTpl = NotifyTpl;\r
520 IEvent->RuntimeData.NotifyFunction = NotifyFunction;\r
521 IEvent->RuntimeData.NotifyContext = (VOID *) NotifyContext;\r
522 IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;\r
523 InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);\r
6652e7be 524 }\r
525\r
526 CoreAcquireEventLock ();\r
527 \r
528 if ((Type & EFI_EVENT_NOTIFY_SIGNAL) != 0x00000000) {\r
529 //\r
530 // The Event's NotifyFunction must be queued whenever the event is signaled\r
531 //\r
532 InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);\r
533 }\r
534 \r
535 CoreReleaseEventLock ();\r
536 \r
537 //\r
538 // Done\r
539 //\r
540 return EFI_SUCCESS;\r
541}\r
542\r
543\r
544\r
545EFI_STATUS\r
546EFIAPI\r
547CoreSignalEvent (\r
548 IN EFI_EVENT UserEvent\r
549 )\r
550/*++\r
551\r
552Routine Description:\r
553\r
554 Signals the event. Queues the event to be notified if needed\r
555 \r
556Arguments:\r
557\r
558 UserEvent - The event to signal\r
559 \r
560Returns:\r
561\r
562 EFI_INVALID_PARAMETER - Parameters are not valid.\r
563 \r
564 EFI_SUCCESS - The event was signaled.\r
565\r
566--*/\r
567{\r
568 IEVENT *Event;\r
569\r
570 Event = UserEvent;\r
571\r
572 if (Event == NULL) {\r
573 return EFI_INVALID_PARAMETER;\r
574 }\r
575\r
576 if (Event->Signature != EVENT_SIGNATURE) {\r
577 return EFI_INVALID_PARAMETER;\r
578 }\r
579\r
580 CoreAcquireEventLock ();\r
581\r
582 //\r
583 // If the event is not already signalled, do so\r
584 //\r
585\r
586 if (Event->SignalCount == 0x00000000) {\r
587 Event->SignalCount++;\r
588\r
589 //\r
590 // If signalling type is a notify function, queue it\r
591 //\r
592 if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {\r
593 if (Event->ExFlag) {\r
594 //\r
595 // The CreateEventEx() style requires all members of the Event Group \r
596 // to be signaled. \r
597 //\r
598 CoreReleaseEventLock ();\r
599 CoreNotifySignalList (&Event->EventGroup);\r
600 CoreAcquireEventLock ();\r
601 } else {\r
602 CoreNotifyEvent (Event);\r
603 }\r
604 }\r
605 }\r
606\r
607 CoreReleaseEventLock ();\r
608 return EFI_SUCCESS;\r
609}\r
610\r
611\r
612EFI_STATUS\r
613EFIAPI\r
614CoreCheckEvent (\r
615 IN EFI_EVENT UserEvent\r
616 )\r
617/*++\r
618\r
619Routine Description:\r
620\r
621 Check the status of an event\r
622 \r
623Arguments:\r
624\r
625 UserEvent - The event to check\r
626 \r
627Returns:\r
628\r
629 EFI_SUCCESS - The event is in the signaled state\r
630 EFI_NOT_READY - The event is not in the signaled state\r
631 EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL\r
632\r
633--*/\r
634\r
635{\r
636 IEVENT *Event;\r
637 EFI_STATUS Status;\r
638\r
639 Event = UserEvent;\r
640\r
641 if (Event == NULL) {\r
642 return EFI_INVALID_PARAMETER;\r
643 }\r
644\r
645 if (Event->Signature != EVENT_SIGNATURE) {\r
646 return EFI_INVALID_PARAMETER;\r
647 }\r
648\r
649 if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {\r
650 return EFI_INVALID_PARAMETER;\r
651 }\r
652\r
653 Status = EFI_NOT_READY;\r
654\r
655 if (!Event->SignalCount && (Event->Type & EFI_EVENT_NOTIFY_WAIT)) {\r
656\r
657 //\r
658 // Queue the wait notify function\r
659 //\r
660\r
661 CoreAcquireEventLock ();\r
662 if (!Event->SignalCount) {\r
663 CoreNotifyEvent (Event);\r
664 }\r
665 CoreReleaseEventLock ();\r
666 }\r
667\r
668 //\r
669 // If the even looks signalled, get the lock and clear it\r
670 //\r
671\r
672 if (Event->SignalCount) {\r
673 CoreAcquireEventLock ();\r
674\r
675 if (Event->SignalCount) {\r
676 Event->SignalCount = 0;\r
677 Status = EFI_SUCCESS;\r
678 }\r
679\r
680 CoreReleaseEventLock ();\r
681 }\r
682\r
683 return Status;\r
684}\r
685\r
686\r
687\r
688EFI_STATUS\r
689EFIAPI\r
690CoreWaitForEvent (\r
691 IN UINTN NumberOfEvents,\r
692 IN EFI_EVENT *UserEvents,\r
693 OUT UINTN *UserIndex\r
694 )\r
695/*++\r
696\r
697Routine Description:\r
698\r
699 Stops execution until an event is signaled.\r
700 \r
701Arguments:\r
702\r
703 NumberOfEvents - The number of events in the UserEvents array\r
704 UserEvents - An array of EFI_EVENT\r
705 UserIndex - Pointer to the index of the event which satisfied the wait condition\r
706 \r
707Returns:\r
708\r
709 EFI_SUCCESS - The event indicated by Index was signaled.\r
710 EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or \r
711 Event was not a valid type\r
712 EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION\r
713\r
714--*/\r
715\r
716{\r
717 EFI_STATUS Status;\r
718 UINTN Index;\r
719\r
720 //\r
721 // Can only WaitForEvent at TPL_APPLICATION\r
722 //\r
723 if (gEfiCurrentTpl != EFI_TPL_APPLICATION) {\r
724 return EFI_UNSUPPORTED;\r
725 }\r
726\r
727 for(;;) {\r
728 \r
729 for(Index = 0; Index < NumberOfEvents; Index++) {\r
730\r
731 Status = CoreCheckEvent (UserEvents[Index]);\r
732\r
733 //\r
734 // provide index of event that caused problem\r
735 //\r
736 if (Status != EFI_NOT_READY) {\r
737 *UserIndex = Index;\r
738 return Status;\r
739 }\r
740 }\r
741\r
742 //\r
743 // This was the location of the Idle loop callback in EFI 1.x reference\r
744 // code. We don't have that concept in this base at this point.\r
745 // \r
746 }\r
747}\r
748\r
749\r
750EFI_STATUS\r
751EFIAPI\r
752CoreCloseEvent (\r
753 IN EFI_EVENT UserEvent\r
754 )\r
755/*++\r
756\r
757Routine Description:\r
758\r
759 Closes an event and frees the event structure.\r
760 \r
761Arguments:\r
762\r
763 UserEvent - Event to close\r
764 \r
765Returns:\r
766\r
767 EFI_INVALID_PARAMETER - Parameters are not valid.\r
768 \r
769 EFI_SUCCESS - The event has been closed\r
770\r
771--*/\r
772\r
773{\r
774 EFI_STATUS Status;\r
775 IEVENT *Event;\r
776\r
777 Event = UserEvent;\r
778\r
779 if (Event == NULL) {\r
780 return EFI_INVALID_PARAMETER;\r
781 }\r
782\r
783 if (Event->Signature != EVENT_SIGNATURE) {\r
784 return EFI_INVALID_PARAMETER;\r
785 }\r
786\r
787 //\r
788 // If it's a timer event, make sure it's not pending\r
789 //\r
790 if (Event->Type & EFI_EVENT_TIMER) {\r
791 CoreSetTimer (Event, TimerCancel, 0);\r
792 }\r
793\r
794 CoreAcquireEventLock ();\r
795\r
796 //\r
797 // If the event is queued somewhere, remove it\r
798 //\r
3ec2611d
LG
799 \r
800 if (Event->RuntimeData.Link.ForwardLink != NULL) {\r
801 RemoveEntryList (&Event->RuntimeData.Link);\r
6652e7be 802 }\r
3ec2611d 803 \r
6652e7be 804 if (Event->NotifyLink.ForwardLink != NULL) {\r
805 RemoveEntryList (&Event->NotifyLink);\r
806 }\r
807\r
808 if (Event->SignalLink.ForwardLink != NULL) {\r
809 RemoveEntryList (&Event->SignalLink);\r
810 }\r
811\r
812 CoreReleaseEventLock ();\r
813\r
814 //\r
815 // If the event is registered on a protocol notify, then remove it from the protocol database\r
816 //\r
817 CoreUnregisterProtocolNotify (Event);\r
818\r
819 Status = CoreFreePool (Event);\r
820 ASSERT_EFI_ERROR (Status);\r
821\r
822 return Status;\r
823}\r