]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Event/Event.c
MdeModulePkg DXE Core: Add Idle event during BootServices WaitForEvent
[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
54cd17e9 4Copyright (c) 2006 - 2011, 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
207 gEventPending &= ~(1 << Priority);\r
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
280 Creates a general-purpose event structure.\r
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
313 Creates a general-purpose event structure\r
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
28a00297 342{\r
343 EFI_STATUS Status;\r
344 IEVENT *IEvent;\r
345 INTN Index;\r
346\r
347\r
51b02d81 348 if (Event == NULL) {\r
28a00297 349 return EFI_INVALID_PARAMETER;\r
350 }\r
351\r
352 //\r
353 // Check to make sure no reserved flags are set\r
354 //\r
355 Status = EFI_INVALID_PARAMETER;\r
356 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {\r
357 if (Type == mEventTable[Index]) {\r
358 Status = EFI_SUCCESS;\r
359 break;\r
360 }\r
361 }\r
362 if(EFI_ERROR (Status)) {\r
363 return EFI_INVALID_PARAMETER;\r
364 }\r
365\r
bb8ffffd 366 //\r
367 // Convert Event type for pre-defined Event groups\r
368 //\r
369 if (EventGroup != NULL) {\r
370 //\r
371 // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE\r
372 // are not valid\r
373 //\r
374 if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {\r
375 return EFI_INVALID_PARAMETER;\r
376 }\r
377 if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {\r
378 Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;\r
379 } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {\r
380 Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;\r
381 }\r
382 } else {\r
383 //\r
384 // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping\r
385 //\r
386 if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {\r
387 EventGroup = &gEfiEventExitBootServicesGuid;\r
388 } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {\r
389 EventGroup = &gEfiEventVirtualAddressChangeGuid;\r
390 }\r
391 }\r
392\r
28a00297 393 //\r
394 // If it's a notify type of event, check its parameters\r
395 //\r
71f68914 396 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
28a00297 397 //\r
398 // Check for an invalid NotifyFunction or NotifyTpl\r
399 //\r
400 if ((NotifyFunction == NULL) ||\r
51b02d81 401 (NotifyTpl <= TPL_APPLICATION) ||\r
28a00297 402 (NotifyTpl >= TPL_HIGH_LEVEL)) {\r
403 return EFI_INVALID_PARAMETER;\r
404 }\r
405\r
406 } else {\r
407 //\r
408 // No notification needed, zero ignored values\r
409 //\r
410 NotifyTpl = 0;\r
411 NotifyFunction = NULL;\r
412 NotifyContext = NULL;\r
413 }\r
414\r
415 //\r
b364eeb0 416 // Allocate and initialize a new event structure.\r
28a00297 417 //\r
b364eeb0 418 if ((Type & EVT_RUNTIME) != 0) {\r
419 IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));\r
420 } else {\r
421 IEvent = AllocateZeroPool (sizeof (IEVENT));\r
422 }\r
423 if (IEvent == NULL) {\r
28a00297 424 return EFI_OUT_OF_RESOURCES;\r
425 }\r
426\r
28a00297 427 IEvent->Signature = EVENT_SIGNATURE;\r
428 IEvent->Type = Type;\r
429\r
430 IEvent->NotifyTpl = NotifyTpl;\r
431 IEvent->NotifyFunction = NotifyFunction;\r
432 IEvent->NotifyContext = (VOID *)NotifyContext;\r
433 if (EventGroup != NULL) {\r
434 CopyGuid (&IEvent->EventGroup, EventGroup);\r
435 IEvent->ExFlag = TRUE;\r
436 }\r
437\r
438 *Event = IEvent;\r
439\r
71f68914 440 if ((Type & EVT_RUNTIME) != 0) {\r
28a00297 441 //\r
442 // Keep a list of all RT events so we can tell the RT AP.\r
443 //\r
444 IEvent->RuntimeData.Type = Type;\r
445 IEvent->RuntimeData.NotifyTpl = NotifyTpl;\r
446 IEvent->RuntimeData.NotifyFunction = NotifyFunction;\r
447 IEvent->RuntimeData.NotifyContext = (VOID *) NotifyContext;\r
448 IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;\r
449 InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);\r
450 }\r
451\r
452 CoreAcquireEventLock ();\r
453\r
454 if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {\r
455 //\r
456 // The Event's NotifyFunction must be queued whenever the event is signaled\r
457 //\r
458 InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);\r
459 }\r
460\r
461 CoreReleaseEventLock ();\r
462\r
463 //\r
464 // Done\r
465 //\r
466 return EFI_SUCCESS;\r
467}\r
468\r
469\r
470\r
28a00297 471\r
162ed594 472/**\r
e94a9ff7 473 Signals the event. Queues the event to be notified if needed.\r
28a00297 474\r
e94a9ff7 475 @param UserEvent The event to signal .\r
28a00297 476\r
022c6d45 477 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 478 @retval EFI_SUCCESS The event was signaled.\r
28a00297 479\r
162ed594 480**/\r
481EFI_STATUS\r
482EFIAPI\r
483CoreSignalEvent (\r
484 IN EFI_EVENT UserEvent\r
485 )\r
28a00297 486{\r
487 IEVENT *Event;\r
488\r
489 Event = UserEvent;\r
490\r
491 if (Event == NULL) {\r
492 return EFI_INVALID_PARAMETER;\r
493 }\r
494\r
495 if (Event->Signature != EVENT_SIGNATURE) {\r
496 return EFI_INVALID_PARAMETER;\r
497 }\r
498\r
499 CoreAcquireEventLock ();\r
500\r
501 //\r
502 // If the event is not already signalled, do so\r
503 //\r
504\r
505 if (Event->SignalCount == 0x00000000) {\r
506 Event->SignalCount++;\r
507\r
508 //\r
509 // If signalling type is a notify function, queue it\r
510 //\r
6e536468 511 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 512 if (Event->ExFlag) {\r
513 //\r
514 // The CreateEventEx() style requires all members of the Event Group\r
515 // to be signaled.\r
516 //\r
517 CoreReleaseEventLock ();\r
518 CoreNotifySignalList (&Event->EventGroup);\r
519 CoreAcquireEventLock ();\r
520 } else {\r
521 CoreNotifyEvent (Event);\r
522 }\r
523 }\r
524 }\r
525\r
526 CoreReleaseEventLock ();\r
527 return EFI_SUCCESS;\r
528}\r
529\r
530\r
162ed594 531\r
532/**\r
533 Check the status of an event.\r
534\r
022c6d45 535 @param UserEvent The event to check\r
162ed594 536\r
022c6d45 537 @retval EFI_SUCCESS The event is in the signaled state\r
538 @retval EFI_NOT_READY The event is not in the signaled state\r
162ed594 539 @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL\r
540\r
541**/\r
28a00297 542EFI_STATUS\r
543EFIAPI\r
544CoreCheckEvent (\r
545 IN EFI_EVENT UserEvent\r
546 )\r
28a00297 547{\r
548 IEVENT *Event;\r
549 EFI_STATUS Status;\r
550\r
551 Event = UserEvent;\r
552\r
553 if (Event == NULL) {\r
554 return EFI_INVALID_PARAMETER;\r
555 }\r
556\r
557 if (Event->Signature != EVENT_SIGNATURE) {\r
558 return EFI_INVALID_PARAMETER;\r
559 }\r
560\r
e94a9ff7 561 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 562 return EFI_INVALID_PARAMETER;\r
563 }\r
564\r
565 Status = EFI_NOT_READY;\r
566\r
6e536468 567 if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {\r
28a00297 568\r
569 //\r
570 // Queue the wait notify function\r
571 //\r
28a00297 572 CoreAcquireEventLock ();\r
6e536468 573 if (Event->SignalCount == 0) {\r
28a00297 574 CoreNotifyEvent (Event);\r
575 }\r
576 CoreReleaseEventLock ();\r
577 }\r
578\r
579 //\r
580 // If the even looks signalled, get the lock and clear it\r
581 //\r
582\r
6e536468 583 if (Event->SignalCount != 0) {\r
28a00297 584 CoreAcquireEventLock ();\r
585\r
6e536468 586 if (Event->SignalCount != 0) {\r
28a00297 587 Event->SignalCount = 0;\r
588 Status = EFI_SUCCESS;\r
589 }\r
590\r
591 CoreReleaseEventLock ();\r
592 }\r
593\r
594 return Status;\r
595}\r
596\r
597\r
598\r
162ed594 599/**\r
600 Stops execution until an event is signaled.\r
601\r
022c6d45 602 @param NumberOfEvents The number of events in the UserEvents array\r
603 @param UserEvents An array of EFI_EVENT\r
604 @param UserIndex Pointer to the index of the event which\r
605 satisfied the wait condition\r
162ed594 606\r
022c6d45 607 @retval EFI_SUCCESS The event indicated by Index was signaled.\r
608 @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification\r
609 function or Event was not a valid type\r
162ed594 610 @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION\r
611\r
612**/\r
28a00297 613EFI_STATUS\r
614EFIAPI\r
615CoreWaitForEvent (\r
616 IN UINTN NumberOfEvents,\r
617 IN EFI_EVENT *UserEvents,\r
618 OUT UINTN *UserIndex\r
619 )\r
28a00297 620{\r
621 EFI_STATUS Status;\r
622 UINTN Index;\r
623\r
624 //\r
625 // Can only WaitForEvent at TPL_APPLICATION\r
626 //\r
627 if (gEfiCurrentTpl != TPL_APPLICATION) {\r
628 return EFI_UNSUPPORTED;\r
629 }\r
630\r
631 for(;;) {\r
632\r
633 for(Index = 0; Index < NumberOfEvents; Index++) {\r
634\r
635 Status = CoreCheckEvent (UserEvents[Index]);\r
636\r
637 //\r
638 // provide index of event that caused problem\r
639 //\r
640 if (Status != EFI_NOT_READY) {\r
641 *UserIndex = Index;\r
642 return Status;\r
643 }\r
644 }\r
645\r
646 //\r
54cd17e9 647 // Signal the Idle event\r
28a00297 648 //\r
54cd17e9 649 CoreSignalEvent (gIdleLoopEvent);\r
28a00297 650 }\r
651}\r
652\r
653\r
162ed594 654/**\r
28a00297 655 Closes an event and frees the event structure.\r
656\r
022c6d45 657 @param UserEvent Event to close\r
28a00297 658\r
022c6d45 659 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 660 @retval EFI_SUCCESS The event has been closed\r
28a00297 661\r
162ed594 662**/\r
663EFI_STATUS\r
664EFIAPI\r
665CoreCloseEvent (\r
666 IN EFI_EVENT UserEvent\r
667 )\r
28a00297 668{\r
669 EFI_STATUS Status;\r
670 IEVENT *Event;\r
671\r
672 Event = UserEvent;\r
673\r
674 if (Event == NULL) {\r
675 return EFI_INVALID_PARAMETER;\r
676 }\r
677\r
678 if (Event->Signature != EVENT_SIGNATURE) {\r
679 return EFI_INVALID_PARAMETER;\r
680 }\r
681\r
682 //\r
683 // If it's a timer event, make sure it's not pending\r
684 //\r
e94a9ff7 685 if ((Event->Type & EVT_TIMER) != 0) {\r
28a00297 686 CoreSetTimer (Event, TimerCancel, 0);\r
687 }\r
688\r
689 CoreAcquireEventLock ();\r
690\r
691 //\r
692 // If the event is queued somewhere, remove it\r
693 //\r
694\r
695 if (Event->RuntimeData.Link.ForwardLink != NULL) {\r
696 RemoveEntryList (&Event->RuntimeData.Link);\r
697 }\r
698\r
699 if (Event->NotifyLink.ForwardLink != NULL) {\r
700 RemoveEntryList (&Event->NotifyLink);\r
701 }\r
702\r
703 if (Event->SignalLink.ForwardLink != NULL) {\r
704 RemoveEntryList (&Event->SignalLink);\r
705 }\r
706\r
707 CoreReleaseEventLock ();\r
708\r
709 //\r
710 // If the event is registered on a protocol notify, then remove it from the protocol database\r
711 //\r
712 CoreUnregisterProtocolNotify (Event);\r
713\r
714 Status = CoreFreePool (Event);\r
715 ASSERT_EFI_ERROR (Status);\r
716\r
717 return Status;\r
718}\r
54cd17e9 719\r