]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Event/Event.c
Update the copyright notice format
[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
cd5ebaa0
HT
4Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
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
25/// gEventQueueLock - Protects the event queus\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
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
162ed594 90\r
91/**\r
92 Enter critical section by acquiring the lock on gEventQueueLock.\r
93\r
94**/\r
28a00297 95VOID\r
96CoreAcquireEventLock (\r
97 VOID\r
98 )\r
28a00297 99{\r
100 CoreAcquireLock (&gEventQueueLock);\r
101}\r
102\r
162ed594 103\r
104/**\r
105 Exit critical section by releasing the lock on gEventQueueLock.\r
106\r
107**/\r
28a00297 108VOID\r
109CoreReleaseEventLock (\r
110 VOID\r
111 )\r
28a00297 112{\r
113 CoreReleaseLock (&gEventQueueLock);\r
114}\r
115\r
116\r
28a00297 117\r
162ed594 118/**\r
c18f12d3 119 Initializes "event" support.\r
28a00297 120\r
162ed594 121 @retval EFI_SUCCESS Always return success\r
28a00297 122\r
162ed594 123**/\r
124EFI_STATUS\r
125CoreInitializeEventServices (\r
126 VOID\r
127 )\r
28a00297 128{\r
129 UINTN Index;\r
130\r
131 for (Index=0; Index <= TPL_HIGH_LEVEL; Index++) {\r
132 InitializeListHead (&gEventQueue[Index]);\r
133 }\r
134\r
135 CoreInitializeTimer ();\r
136\r
137 return EFI_SUCCESS;\r
138}\r
139\r
140\r
28a00297 141\r
162ed594 142/**\r
28a00297 143 Dispatches all pending events.\r
144\r
022c6d45 145 @param Priority The task priority level of event notifications\r
162ed594 146 to dispatch\r
28a00297 147\r
162ed594 148**/\r
149VOID\r
150CoreDispatchEventNotifies (\r
151 IN EFI_TPL Priority\r
152 )\r
28a00297 153{\r
154 IEVENT *Event;\r
155 LIST_ENTRY *Head;\r
156\r
157 CoreAcquireEventLock ();\r
158 ASSERT (gEventQueueLock.OwnerTpl == Priority);\r
159 Head = &gEventQueue[Priority];\r
160\r
161 //\r
162 // Dispatch all the pending notifications\r
163 //\r
164 while (!IsListEmpty (Head)) {\r
165\r
166 Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);\r
167 RemoveEntryList (&Event->NotifyLink);\r
168\r
169 Event->NotifyLink.ForwardLink = NULL;\r
170\r
171 //\r
172 // Only clear the SIGNAL status if it is a SIGNAL type event.\r
173 // WAIT type events are only cleared in CheckEvent()\r
174 //\r
6e536468 175 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 176 Event->SignalCount = 0;\r
177 }\r
178\r
179 CoreReleaseEventLock ();\r
180\r
181 //\r
182 // Notify this event\r
183 //\r
184 ASSERT (Event->NotifyFunction != NULL);\r
185 Event->NotifyFunction (Event, Event->NotifyContext);\r
186\r
187 //\r
188 // Check for next pending event\r
189 //\r
190 CoreAcquireEventLock ();\r
191 }\r
192\r
193 gEventPending &= ~(1 << Priority);\r
194 CoreReleaseEventLock ();\r
195}\r
196\r
197\r
162ed594 198\r
199/**\r
200 Queues the event's notification function to fire.\r
201\r
202 @param Event The Event to notify\r
203\r
204**/\r
28a00297 205VOID\r
206CoreNotifyEvent (\r
207 IN IEVENT *Event\r
208 )\r
28a00297 209{\r
210\r
211 //\r
212 // Event database must be locked\r
213 //\r
214 ASSERT_LOCKED (&gEventQueueLock);\r
215\r
216 //\r
217 // If the event is queued somewhere, remove it\r
218 //\r
219\r
220 if (Event->NotifyLink.ForwardLink != NULL) {\r
221 RemoveEntryList (&Event->NotifyLink);\r
222 Event->NotifyLink.ForwardLink = NULL;\r
223 }\r
224\r
225 //\r
226 // Queue the event to the pending notification list\r
227 //\r
228\r
229 InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);\r
230 gEventPending |= (UINTN)(1 << Event->NotifyTpl);\r
231}\r
232\r
233\r
234\r
162ed594 235\r
236/**\r
237 Signals all events in the EventGroup.\r
238\r
239 @param EventGroup The list to signal\r
240\r
241**/\r
28a00297 242VOID\r
243CoreNotifySignalList (\r
244 IN EFI_GUID *EventGroup\r
245 )\r
28a00297 246{\r
247 LIST_ENTRY *Link;\r
248 LIST_ENTRY *Head;\r
249 IEVENT *Event;\r
250\r
251 CoreAcquireEventLock ();\r
252\r
253 Head = &gEventSignalQueue;\r
254 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
255 Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);\r
256 if (CompareGuid (&Event->EventGroup, EventGroup)) {\r
257 CoreNotifyEvent (Event);\r
258 }\r
259 }\r
260\r
261 CoreReleaseEventLock ();\r
262}\r
263\r
162ed594 264\r
265/**\r
266 Creates a general-purpose event structure.\r
267\r
022c6d45 268 @param Type The type of event to create and its mode and\r
269 attributes\r
270 @param NotifyTpl The task priority level of event notifications\r
271 @param NotifyFunction Pointer to the events notification function\r
272 @param NotifyContext Pointer to the notification functions context;\r
273 corresponds to parameter "Context" in the\r
274 notification function\r
275 @param Event Pointer to the newly created event if the call\r
276 succeeds; undefined otherwise\r
277\r
278 @retval EFI_SUCCESS The event structure was created\r
279 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
162ed594 280 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
281\r
282**/\r
28a00297 283EFI_STATUS\r
284EFIAPI\r
285CoreCreateEvent (\r
286 IN UINT32 Type,\r
287 IN EFI_TPL NotifyTpl,\r
288 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
289 IN VOID *NotifyContext, OPTIONAL\r
290 OUT EFI_EVENT *Event\r
291 )\r
28a00297 292{\r
bb8ffffd 293 return CoreCreateEventEx (Type, NotifyTpl, NotifyFunction, NotifyContext, NULL, Event);\r
28a00297 294}\r
295\r
296\r
162ed594 297\r
298/**\r
299 Creates a general-purpose event structure\r
300\r
022c6d45 301 @param Type The type of event to create and its mode and\r
302 attributes\r
303 @param NotifyTpl The task priority level of event notifications\r
304 @param NotifyFunction Pointer to the events notification function\r
305 @param NotifyContext Pointer to the notification functions context;\r
306 corresponds to parameter "Context" in the\r
307 notification function\r
308 @param EventGroup GUID for EventGroup if NULL act the same as\r
309 gBS->CreateEvent().\r
310 @param Event Pointer to the newly created event if the call\r
311 succeeds; undefined otherwise\r
312\r
313 @retval EFI_SUCCESS The event structure was created\r
314 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
162ed594 315 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
316\r
317**/\r
28a00297 318EFI_STATUS\r
319EFIAPI\r
320CoreCreateEventEx (\r
321 IN UINT32 Type,\r
322 IN EFI_TPL NotifyTpl,\r
323 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
324 IN CONST VOID *NotifyContext, OPTIONAL\r
325 IN CONST EFI_GUID *EventGroup, OPTIONAL\r
326 OUT EFI_EVENT *Event\r
327 )\r
28a00297 328{\r
329 EFI_STATUS Status;\r
330 IEVENT *IEvent;\r
331 INTN Index;\r
332\r
333\r
51b02d81 334 if (Event == NULL) {\r
28a00297 335 return EFI_INVALID_PARAMETER;\r
336 }\r
337\r
338 //\r
339 // Check to make sure no reserved flags are set\r
340 //\r
341 Status = EFI_INVALID_PARAMETER;\r
342 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {\r
343 if (Type == mEventTable[Index]) {\r
344 Status = EFI_SUCCESS;\r
345 break;\r
346 }\r
347 }\r
348 if(EFI_ERROR (Status)) {\r
349 return EFI_INVALID_PARAMETER;\r
350 }\r
351\r
bb8ffffd 352 //\r
353 // Convert Event type for pre-defined Event groups\r
354 //\r
355 if (EventGroup != NULL) {\r
356 //\r
357 // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE\r
358 // are not valid\r
359 //\r
360 if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {\r
361 return EFI_INVALID_PARAMETER;\r
362 }\r
363 if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {\r
364 Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;\r
365 } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {\r
366 Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;\r
367 }\r
368 } else {\r
369 //\r
370 // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping\r
371 //\r
372 if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {\r
373 EventGroup = &gEfiEventExitBootServicesGuid;\r
374 } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {\r
375 EventGroup = &gEfiEventVirtualAddressChangeGuid;\r
376 }\r
377 }\r
378\r
28a00297 379 //\r
380 // If it's a notify type of event, check its parameters\r
381 //\r
71f68914 382 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
28a00297 383 //\r
384 // Check for an invalid NotifyFunction or NotifyTpl\r
385 //\r
386 if ((NotifyFunction == NULL) ||\r
51b02d81 387 (NotifyTpl <= TPL_APPLICATION) ||\r
28a00297 388 (NotifyTpl >= TPL_HIGH_LEVEL)) {\r
389 return EFI_INVALID_PARAMETER;\r
390 }\r
391\r
392 } else {\r
393 //\r
394 // No notification needed, zero ignored values\r
395 //\r
396 NotifyTpl = 0;\r
397 NotifyFunction = NULL;\r
398 NotifyContext = NULL;\r
399 }\r
400\r
401 //\r
b364eeb0 402 // Allocate and initialize a new event structure.\r
28a00297 403 //\r
b364eeb0 404 if ((Type & EVT_RUNTIME) != 0) {\r
405 IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));\r
406 } else {\r
407 IEvent = AllocateZeroPool (sizeof (IEVENT));\r
408 }\r
409 if (IEvent == NULL) {\r
28a00297 410 return EFI_OUT_OF_RESOURCES;\r
411 }\r
412\r
28a00297 413 IEvent->Signature = EVENT_SIGNATURE;\r
414 IEvent->Type = Type;\r
415\r
416 IEvent->NotifyTpl = NotifyTpl;\r
417 IEvent->NotifyFunction = NotifyFunction;\r
418 IEvent->NotifyContext = (VOID *)NotifyContext;\r
419 if (EventGroup != NULL) {\r
420 CopyGuid (&IEvent->EventGroup, EventGroup);\r
421 IEvent->ExFlag = TRUE;\r
422 }\r
423\r
424 *Event = IEvent;\r
425\r
71f68914 426 if ((Type & EVT_RUNTIME) != 0) {\r
28a00297 427 //\r
428 // Keep a list of all RT events so we can tell the RT AP.\r
429 //\r
430 IEvent->RuntimeData.Type = Type;\r
431 IEvent->RuntimeData.NotifyTpl = NotifyTpl;\r
432 IEvent->RuntimeData.NotifyFunction = NotifyFunction;\r
433 IEvent->RuntimeData.NotifyContext = (VOID *) NotifyContext;\r
434 IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;\r
435 InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);\r
436 }\r
437\r
438 CoreAcquireEventLock ();\r
439\r
440 if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {\r
441 //\r
442 // The Event's NotifyFunction must be queued whenever the event is signaled\r
443 //\r
444 InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);\r
445 }\r
446\r
447 CoreReleaseEventLock ();\r
448\r
449 //\r
450 // Done\r
451 //\r
452 return EFI_SUCCESS;\r
453}\r
454\r
455\r
456\r
28a00297 457\r
162ed594 458/**\r
e94a9ff7 459 Signals the event. Queues the event to be notified if needed.\r
28a00297 460\r
e94a9ff7 461 @param UserEvent The event to signal .\r
28a00297 462\r
022c6d45 463 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 464 @retval EFI_SUCCESS The event was signaled.\r
28a00297 465\r
162ed594 466**/\r
467EFI_STATUS\r
468EFIAPI\r
469CoreSignalEvent (\r
470 IN EFI_EVENT UserEvent\r
471 )\r
28a00297 472{\r
473 IEVENT *Event;\r
474\r
475 Event = UserEvent;\r
476\r
477 if (Event == NULL) {\r
478 return EFI_INVALID_PARAMETER;\r
479 }\r
480\r
481 if (Event->Signature != EVENT_SIGNATURE) {\r
482 return EFI_INVALID_PARAMETER;\r
483 }\r
484\r
485 CoreAcquireEventLock ();\r
486\r
487 //\r
488 // If the event is not already signalled, do so\r
489 //\r
490\r
491 if (Event->SignalCount == 0x00000000) {\r
492 Event->SignalCount++;\r
493\r
494 //\r
495 // If signalling type is a notify function, queue it\r
496 //\r
6e536468 497 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 498 if (Event->ExFlag) {\r
499 //\r
500 // The CreateEventEx() style requires all members of the Event Group\r
501 // to be signaled.\r
502 //\r
503 CoreReleaseEventLock ();\r
504 CoreNotifySignalList (&Event->EventGroup);\r
505 CoreAcquireEventLock ();\r
506 } else {\r
507 CoreNotifyEvent (Event);\r
508 }\r
509 }\r
510 }\r
511\r
512 CoreReleaseEventLock ();\r
513 return EFI_SUCCESS;\r
514}\r
515\r
516\r
162ed594 517\r
518/**\r
519 Check the status of an event.\r
520\r
022c6d45 521 @param UserEvent The event to check\r
162ed594 522\r
022c6d45 523 @retval EFI_SUCCESS The event is in the signaled state\r
524 @retval EFI_NOT_READY The event is not in the signaled state\r
162ed594 525 @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL\r
526\r
527**/\r
28a00297 528EFI_STATUS\r
529EFIAPI\r
530CoreCheckEvent (\r
531 IN EFI_EVENT UserEvent\r
532 )\r
28a00297 533{\r
534 IEVENT *Event;\r
535 EFI_STATUS Status;\r
536\r
537 Event = UserEvent;\r
538\r
539 if (Event == NULL) {\r
540 return EFI_INVALID_PARAMETER;\r
541 }\r
542\r
543 if (Event->Signature != EVENT_SIGNATURE) {\r
544 return EFI_INVALID_PARAMETER;\r
545 }\r
546\r
e94a9ff7 547 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 548 return EFI_INVALID_PARAMETER;\r
549 }\r
550\r
551 Status = EFI_NOT_READY;\r
552\r
6e536468 553 if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {\r
28a00297 554\r
555 //\r
556 // Queue the wait notify function\r
557 //\r
28a00297 558 CoreAcquireEventLock ();\r
6e536468 559 if (Event->SignalCount == 0) {\r
28a00297 560 CoreNotifyEvent (Event);\r
561 }\r
562 CoreReleaseEventLock ();\r
563 }\r
564\r
565 //\r
566 // If the even looks signalled, get the lock and clear it\r
567 //\r
568\r
6e536468 569 if (Event->SignalCount != 0) {\r
28a00297 570 CoreAcquireEventLock ();\r
571\r
6e536468 572 if (Event->SignalCount != 0) {\r
28a00297 573 Event->SignalCount = 0;\r
574 Status = EFI_SUCCESS;\r
575 }\r
576\r
577 CoreReleaseEventLock ();\r
578 }\r
579\r
580 return Status;\r
581}\r
582\r
583\r
584\r
162ed594 585/**\r
586 Stops execution until an event is signaled.\r
587\r
022c6d45 588 @param NumberOfEvents The number of events in the UserEvents array\r
589 @param UserEvents An array of EFI_EVENT\r
590 @param UserIndex Pointer to the index of the event which\r
591 satisfied the wait condition\r
162ed594 592\r
022c6d45 593 @retval EFI_SUCCESS The event indicated by Index was signaled.\r
594 @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification\r
595 function or Event was not a valid type\r
162ed594 596 @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION\r
597\r
598**/\r
28a00297 599EFI_STATUS\r
600EFIAPI\r
601CoreWaitForEvent (\r
602 IN UINTN NumberOfEvents,\r
603 IN EFI_EVENT *UserEvents,\r
604 OUT UINTN *UserIndex\r
605 )\r
28a00297 606{\r
607 EFI_STATUS Status;\r
608 UINTN Index;\r
609\r
610 //\r
611 // Can only WaitForEvent at TPL_APPLICATION\r
612 //\r
613 if (gEfiCurrentTpl != TPL_APPLICATION) {\r
614 return EFI_UNSUPPORTED;\r
615 }\r
616\r
617 for(;;) {\r
618\r
619 for(Index = 0; Index < NumberOfEvents; Index++) {\r
620\r
621 Status = CoreCheckEvent (UserEvents[Index]);\r
622\r
623 //\r
624 // provide index of event that caused problem\r
625 //\r
626 if (Status != EFI_NOT_READY) {\r
627 *UserIndex = Index;\r
628 return Status;\r
629 }\r
630 }\r
631\r
632 //\r
633 // This was the location of the Idle loop callback in EFI 1.x reference\r
634 // code. We don't have that concept in this base at this point.\r
635 //\r
636 }\r
637}\r
638\r
639\r
162ed594 640/**\r
28a00297 641 Closes an event and frees the event structure.\r
642\r
022c6d45 643 @param UserEvent Event to close\r
28a00297 644\r
022c6d45 645 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 646 @retval EFI_SUCCESS The event has been closed\r
28a00297 647\r
162ed594 648**/\r
649EFI_STATUS\r
650EFIAPI\r
651CoreCloseEvent (\r
652 IN EFI_EVENT UserEvent\r
653 )\r
28a00297 654{\r
655 EFI_STATUS Status;\r
656 IEVENT *Event;\r
657\r
658 Event = UserEvent;\r
659\r
660 if (Event == NULL) {\r
661 return EFI_INVALID_PARAMETER;\r
662 }\r
663\r
664 if (Event->Signature != EVENT_SIGNATURE) {\r
665 return EFI_INVALID_PARAMETER;\r
666 }\r
667\r
668 //\r
669 // If it's a timer event, make sure it's not pending\r
670 //\r
e94a9ff7 671 if ((Event->Type & EVT_TIMER) != 0) {\r
28a00297 672 CoreSetTimer (Event, TimerCancel, 0);\r
673 }\r
674\r
675 CoreAcquireEventLock ();\r
676\r
677 //\r
678 // If the event is queued somewhere, remove it\r
679 //\r
680\r
681 if (Event->RuntimeData.Link.ForwardLink != NULL) {\r
682 RemoveEntryList (&Event->RuntimeData.Link);\r
683 }\r
684\r
685 if (Event->NotifyLink.ForwardLink != NULL) {\r
686 RemoveEntryList (&Event->NotifyLink);\r
687 }\r
688\r
689 if (Event->SignalLink.ForwardLink != NULL) {\r
690 RemoveEntryList (&Event->SignalLink);\r
691 }\r
692\r
693 CoreReleaseEventLock ();\r
694\r
695 //\r
696 // If the event is registered on a protocol notify, then remove it from the protocol database\r
697 //\r
698 CoreUnregisterProtocolNotify (Event);\r
699\r
700 Status = CoreFreePool (Event);\r
701 ASSERT_EFI_ERROR (Status);\r
702\r
703 return Status;\r
704}\r