]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Event/Event.c
Fix some typo.
[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
23c98c94 4Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
28a00297 5All rights reserved. This 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
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
402 // Allcoate and initialize a new event structure.\r
403 //\r
404 Status = CoreAllocatePool (\r
71f68914 405 ((Type & EVT_RUNTIME) != 0) ? EfiRuntimeServicesData: EfiBootServicesData,\r
28a00297 406 sizeof (IEVENT),\r
407 (VOID **)&IEvent\r
408 );\r
409 if (EFI_ERROR (Status)) {\r
410 return EFI_OUT_OF_RESOURCES;\r
411 }\r
412\r
e94a9ff7 413 ZeroMem (IEvent, sizeof (IEVENT));\r
28a00297 414\r
415 IEvent->Signature = EVENT_SIGNATURE;\r
416 IEvent->Type = Type;\r
417\r
418 IEvent->NotifyTpl = NotifyTpl;\r
419 IEvent->NotifyFunction = NotifyFunction;\r
420 IEvent->NotifyContext = (VOID *)NotifyContext;\r
421 if (EventGroup != NULL) {\r
422 CopyGuid (&IEvent->EventGroup, EventGroup);\r
423 IEvent->ExFlag = TRUE;\r
424 }\r
425\r
426 *Event = IEvent;\r
427\r
71f68914 428 if ((Type & EVT_RUNTIME) != 0) {\r
28a00297 429 //\r
430 // Keep a list of all RT events so we can tell the RT AP.\r
431 //\r
432 IEvent->RuntimeData.Type = Type;\r
433 IEvent->RuntimeData.NotifyTpl = NotifyTpl;\r
434 IEvent->RuntimeData.NotifyFunction = NotifyFunction;\r
435 IEvent->RuntimeData.NotifyContext = (VOID *) NotifyContext;\r
436 IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;\r
437 InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);\r
438 }\r
439\r
440 CoreAcquireEventLock ();\r
441\r
442 if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {\r
443 //\r
444 // The Event's NotifyFunction must be queued whenever the event is signaled\r
445 //\r
446 InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);\r
447 }\r
448\r
449 CoreReleaseEventLock ();\r
450\r
451 //\r
452 // Done\r
453 //\r
454 return EFI_SUCCESS;\r
455}\r
456\r
457\r
458\r
28a00297 459\r
162ed594 460/**\r
e94a9ff7 461 Signals the event. Queues the event to be notified if needed.\r
28a00297 462\r
e94a9ff7 463 @param UserEvent The event to signal .\r
28a00297 464\r
022c6d45 465 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 466 @retval EFI_SUCCESS The event was signaled.\r
28a00297 467\r
162ed594 468**/\r
469EFI_STATUS\r
470EFIAPI\r
471CoreSignalEvent (\r
472 IN EFI_EVENT UserEvent\r
473 )\r
28a00297 474{\r
475 IEVENT *Event;\r
476\r
477 Event = UserEvent;\r
478\r
479 if (Event == NULL) {\r
480 return EFI_INVALID_PARAMETER;\r
481 }\r
482\r
483 if (Event->Signature != EVENT_SIGNATURE) {\r
484 return EFI_INVALID_PARAMETER;\r
485 }\r
486\r
487 CoreAcquireEventLock ();\r
488\r
489 //\r
490 // If the event is not already signalled, do so\r
491 //\r
492\r
493 if (Event->SignalCount == 0x00000000) {\r
494 Event->SignalCount++;\r
495\r
496 //\r
497 // If signalling type is a notify function, queue it\r
498 //\r
6e536468 499 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 500 if (Event->ExFlag) {\r
501 //\r
502 // The CreateEventEx() style requires all members of the Event Group\r
503 // to be signaled.\r
504 //\r
505 CoreReleaseEventLock ();\r
506 CoreNotifySignalList (&Event->EventGroup);\r
507 CoreAcquireEventLock ();\r
508 } else {\r
509 CoreNotifyEvent (Event);\r
510 }\r
511 }\r
512 }\r
513\r
514 CoreReleaseEventLock ();\r
515 return EFI_SUCCESS;\r
516}\r
517\r
518\r
162ed594 519\r
520/**\r
521 Check the status of an event.\r
522\r
022c6d45 523 @param UserEvent The event to check\r
162ed594 524\r
022c6d45 525 @retval EFI_SUCCESS The event is in the signaled state\r
526 @retval EFI_NOT_READY The event is not in the signaled state\r
162ed594 527 @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL\r
528\r
529**/\r
28a00297 530EFI_STATUS\r
531EFIAPI\r
532CoreCheckEvent (\r
533 IN EFI_EVENT UserEvent\r
534 )\r
28a00297 535{\r
536 IEVENT *Event;\r
537 EFI_STATUS Status;\r
538\r
539 Event = UserEvent;\r
540\r
541 if (Event == NULL) {\r
542 return EFI_INVALID_PARAMETER;\r
543 }\r
544\r
545 if (Event->Signature != EVENT_SIGNATURE) {\r
546 return EFI_INVALID_PARAMETER;\r
547 }\r
548\r
e94a9ff7 549 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 550 return EFI_INVALID_PARAMETER;\r
551 }\r
552\r
553 Status = EFI_NOT_READY;\r
554\r
6e536468 555 if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {\r
28a00297 556\r
557 //\r
558 // Queue the wait notify function\r
559 //\r
28a00297 560 CoreAcquireEventLock ();\r
6e536468 561 if (Event->SignalCount == 0) {\r
28a00297 562 CoreNotifyEvent (Event);\r
563 }\r
564 CoreReleaseEventLock ();\r
565 }\r
566\r
567 //\r
568 // If the even looks signalled, get the lock and clear it\r
569 //\r
570\r
6e536468 571 if (Event->SignalCount != 0) {\r
28a00297 572 CoreAcquireEventLock ();\r
573\r
6e536468 574 if (Event->SignalCount != 0) {\r
28a00297 575 Event->SignalCount = 0;\r
576 Status = EFI_SUCCESS;\r
577 }\r
578\r
579 CoreReleaseEventLock ();\r
580 }\r
581\r
582 return Status;\r
583}\r
584\r
585\r
586\r
162ed594 587/**\r
588 Stops execution until an event is signaled.\r
589\r
022c6d45 590 @param NumberOfEvents The number of events in the UserEvents array\r
591 @param UserEvents An array of EFI_EVENT\r
592 @param UserIndex Pointer to the index of the event which\r
593 satisfied the wait condition\r
162ed594 594\r
022c6d45 595 @retval EFI_SUCCESS The event indicated by Index was signaled.\r
596 @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification\r
597 function or Event was not a valid type\r
162ed594 598 @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION\r
599\r
600**/\r
28a00297 601EFI_STATUS\r
602EFIAPI\r
603CoreWaitForEvent (\r
604 IN UINTN NumberOfEvents,\r
605 IN EFI_EVENT *UserEvents,\r
606 OUT UINTN *UserIndex\r
607 )\r
28a00297 608{\r
609 EFI_STATUS Status;\r
610 UINTN Index;\r
611\r
612 //\r
613 // Can only WaitForEvent at TPL_APPLICATION\r
614 //\r
615 if (gEfiCurrentTpl != TPL_APPLICATION) {\r
616 return EFI_UNSUPPORTED;\r
617 }\r
618\r
619 for(;;) {\r
620\r
621 for(Index = 0; Index < NumberOfEvents; Index++) {\r
622\r
623 Status = CoreCheckEvent (UserEvents[Index]);\r
624\r
625 //\r
626 // provide index of event that caused problem\r
627 //\r
628 if (Status != EFI_NOT_READY) {\r
629 *UserIndex = Index;\r
630 return Status;\r
631 }\r
632 }\r
633\r
634 //\r
635 // This was the location of the Idle loop callback in EFI 1.x reference\r
636 // code. We don't have that concept in this base at this point.\r
637 //\r
638 }\r
639}\r
640\r
641\r
162ed594 642/**\r
28a00297 643 Closes an event and frees the event structure.\r
644\r
022c6d45 645 @param UserEvent Event to close\r
28a00297 646\r
022c6d45 647 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 648 @retval EFI_SUCCESS The event has been closed\r
28a00297 649\r
162ed594 650**/\r
651EFI_STATUS\r
652EFIAPI\r
653CoreCloseEvent (\r
654 IN EFI_EVENT UserEvent\r
655 )\r
28a00297 656{\r
657 EFI_STATUS Status;\r
658 IEVENT *Event;\r
659\r
660 Event = UserEvent;\r
661\r
662 if (Event == NULL) {\r
663 return EFI_INVALID_PARAMETER;\r
664 }\r
665\r
666 if (Event->Signature != EVENT_SIGNATURE) {\r
667 return EFI_INVALID_PARAMETER;\r
668 }\r
669\r
670 //\r
671 // If it's a timer event, make sure it's not pending\r
672 //\r
e94a9ff7 673 if ((Event->Type & EVT_TIMER) != 0) {\r
28a00297 674 CoreSetTimer (Event, TimerCancel, 0);\r
675 }\r
676\r
677 CoreAcquireEventLock ();\r
678\r
679 //\r
680 // If the event is queued somewhere, remove it\r
681 //\r
682\r
683 if (Event->RuntimeData.Link.ForwardLink != NULL) {\r
684 RemoveEntryList (&Event->RuntimeData.Link);\r
685 }\r
686\r
687 if (Event->NotifyLink.ForwardLink != NULL) {\r
688 RemoveEntryList (&Event->NotifyLink);\r
689 }\r
690\r
691 if (Event->SignalLink.ForwardLink != NULL) {\r
692 RemoveEntryList (&Event->SignalLink);\r
693 }\r
694\r
695 CoreReleaseEventLock ();\r
696\r
697 //\r
698 // If the event is registered on a protocol notify, then remove it from the protocol database\r
699 //\r
700 CoreUnregisterProtocolNotify (Event);\r
701\r
702 Status = CoreFreePool (Event);\r
703 ASSERT_EFI_ERROR (Status);\r
704\r
705 return Status;\r
706}\r