TianoCore EDK2 master
Loading...
Searching...
No Matches
Event.c
Go to the documentation of this file.
1
10#include "DxeMain.h"
11#include "Event.h"
12
16EFI_TPL gEfiCurrentTpl = TPL_APPLICATION;
17
22
26LIST_ENTRY gEventQueue[TPL_HIGH_LEVEL + 1];
27
32
37
41UINT32 mEventTable[] = {
46 EVT_TIMER | EVT_NOTIFY_SIGNAL,
51 EVT_TIMER,
56 EVT_NOTIFY_WAIT,
61 EVT_NOTIFY_SIGNAL,
65 EVT_SIGNAL_EXIT_BOOT_SERVICES,
69 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
70
76 0x00000000,
81 EVT_TIMER | EVT_NOTIFY_WAIT,
82};
83
88
93VOID
95 VOID
96 )
97{
99}
100
105VOID
107 VOID
108 )
109{
111}
112
121 VOID
122 )
123{
124 UINTN Index;
125
126 for (Index = 0; Index <= TPL_HIGH_LEVEL; Index++) {
128 }
129
131
133 EVT_NOTIFY_SIGNAL,
134 TPL_NOTIFY,
136 NULL,
137 &gIdleLoopEventGuid,
139 );
140
141 return EFI_SUCCESS;
142}
143
151VOID
153 IN EFI_TPL Priority
154 )
155{
156 IEVENT *Event;
157 LIST_ENTRY *Head;
158
160 ASSERT (gEventQueueLock.OwnerTpl == Priority);
161 Head = &gEventQueue[Priority];
162
163 //
164 // Dispatch all the pending notifications
165 //
166 while (!IsListEmpty (Head)) {
167 Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);
168 RemoveEntryList (&Event->NotifyLink);
169
170 Event->NotifyLink.ForwardLink = NULL;
171
172 //
173 // Only clear the SIGNAL status if it is a SIGNAL type event.
174 // WAIT type events are only cleared in CheckEvent()
175 //
176 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
177 Event->SignalCount = 0;
178 }
179
181
182 //
183 // Notify this event
184 //
185 ASSERT (Event->NotifyFunction != NULL);
186 Event->NotifyFunction (Event, Event->NotifyContext);
187
188 //
189 // Check for next pending event
190 //
192 }
193
194 gEventPending &= ~(UINTN)(1 << Priority);
196}
197
204VOID
206 IN IEVENT *Event
207 )
208{
209 //
210 // Event database must be locked
211 //
213
214 //
215 // If the event is queued somewhere, remove it
216 //
217
218 if (Event->NotifyLink.ForwardLink != NULL) {
219 RemoveEntryList (&Event->NotifyLink);
220 Event->NotifyLink.ForwardLink = NULL;
221 }
222
223 //
224 // Queue the event to the pending notification list
225 //
226
227 InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);
228 gEventPending |= (UINTN)(1 << Event->NotifyTpl);
229}
230
237VOID
239 IN EFI_GUID *EventGroup
240 )
241{
242 LIST_ENTRY *Link;
243 LIST_ENTRY *Head;
244 IEVENT *Event;
245
247
248 Head = &gEventSignalQueue;
249 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
250 Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);
251 if (CompareGuid (&Event->EventGroup, EventGroup)) {
252 CoreNotifyEvent (Event);
253 }
254 }
255
257}
258
278EFIAPI
280 IN UINT32 Type,
281 IN EFI_TPL NotifyTpl,
283 IN VOID *NotifyContext OPTIONAL,
284 OUT EFI_EVENT *Event
285 )
286{
287 return CoreCreateEventEx (Type, NotifyTpl, NotifyFunction, NotifyContext, NULL, Event);
288}
289
311EFIAPI
313 IN UINT32 Type,
314 IN EFI_TPL NotifyTpl,
316 IN CONST VOID *NotifyContext OPTIONAL,
317 IN CONST EFI_GUID *EventGroup OPTIONAL,
318 OUT EFI_EVENT *Event
319 )
320{
321 //
322 // If it's a notify type of event, check for invalid NotifyTpl
323 //
324 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {
325 if ((NotifyTpl != TPL_APPLICATION) &&
326 (NotifyTpl != TPL_CALLBACK) &&
327 (NotifyTpl != TPL_NOTIFY))
328 {
329 return EFI_INVALID_PARAMETER;
330 }
331 }
332
333 return CoreCreateEventInternal (Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, Event);
334}
335
357EFIAPI
359 IN UINT32 Type,
360 IN EFI_TPL NotifyTpl,
362 IN CONST VOID *NotifyContext OPTIONAL,
363 IN CONST EFI_GUID *EventGroup OPTIONAL,
364 OUT EFI_EVENT *Event
365 )
366{
367 EFI_STATUS Status;
368 IEVENT *IEvent;
369 INTN Index;
370
371 if (Event == NULL) {
372 return EFI_INVALID_PARAMETER;
373 }
374
375 //
376 // Check to make sure no reserved flags are set
377 //
378 Status = EFI_INVALID_PARAMETER;
379 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
380 if (Type == mEventTable[Index]) {
381 Status = EFI_SUCCESS;
382 break;
383 }
384 }
385
386 if (EFI_ERROR (Status)) {
387 return EFI_INVALID_PARAMETER;
388 }
389
390 //
391 // Convert Event type for pre-defined Event groups
392 //
393 if (EventGroup != NULL) {
394 //
395 // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
396 // are not valid
397 //
398 if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {
399 return EFI_INVALID_PARAMETER;
400 }
401
402 if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {
403 Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;
404 } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {
405 Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;
406 }
407 } else {
408 //
409 // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping
410 //
411 if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {
412 EventGroup = &gEfiEventExitBootServicesGuid;
413 } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
414 EventGroup = &gEfiEventVirtualAddressChangeGuid;
415 }
416 }
417
418 //
419 // If it's a notify type of event, check its parameters
420 //
421 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {
422 //
423 // Check for an invalid NotifyFunction or NotifyTpl
424 //
425 if ((NotifyFunction == NULL) ||
426 (NotifyTpl <= TPL_APPLICATION) ||
427 (NotifyTpl >= TPL_HIGH_LEVEL))
428 {
429 return EFI_INVALID_PARAMETER;
430 }
431 } else {
432 //
433 // No notification needed, zero ignored values
434 //
435 NotifyTpl = 0;
437 NotifyContext = NULL;
438 }
439
440 //
441 // Allocate and initialize a new event structure.
442 //
443 if ((Type & EVT_RUNTIME) != 0) {
444 IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));
445 } else {
446 IEvent = AllocateZeroPool (sizeof (IEVENT));
447 }
448
449 if (IEvent == NULL) {
450 return EFI_OUT_OF_RESOURCES;
451 }
452
453 IEvent->Signature = EVENT_SIGNATURE;
454 IEvent->Type = Type;
455
456 IEvent->NotifyTpl = NotifyTpl;
457 IEvent->NotifyFunction = NotifyFunction;
458 IEvent->NotifyContext = (VOID *)NotifyContext;
459 if (EventGroup != NULL) {
460 CopyGuid (&IEvent->EventGroup, EventGroup);
461 IEvent->ExFlag |= EVT_EXFLAG_EVENT_GROUP;
462 }
463
464 *Event = IEvent;
465
466 if ((Type & EVT_RUNTIME) != 0) {
467 //
468 // Keep a list of all RT events so we can tell the RT AP.
469 //
470 IEvent->RuntimeData.Type = Type;
471 IEvent->RuntimeData.NotifyTpl = NotifyTpl;
473 IEvent->RuntimeData.NotifyContext = (VOID *)NotifyContext;
474 //
475 // Work around the bug in the Platform Init specification (v1.7), reported
476 // as Mantis#2017: "EFI_RUNTIME_EVENT_ENTRY.Event" should have type
477 // EFI_EVENT, not (EFI_EVENT*). The PI spec documents the field correctly
478 // as "The EFI_EVENT returned by CreateEvent()", but the type of the field
479 // doesn't match the natural language description. Therefore we need an
480 // explicit cast here.
481 //
482 IEvent->RuntimeData.Event = (EFI_EVENT *)IEvent;
483 InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);
484 }
485
487
488 if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {
489 //
490 // The Event's NotifyFunction must be queued whenever the event is signaled
491 //
493 }
494
496
497 //
498 // Done
499 //
500 return EFI_SUCCESS;
501}
502
513EFIAPI
515 IN EFI_EVENT UserEvent
516 )
517{
518 IEVENT *Event;
519
520 Event = UserEvent;
521
522 if (Event == NULL) {
523 return EFI_INVALID_PARAMETER;
524 }
525
526 if (Event->Signature != EVENT_SIGNATURE) {
527 return EFI_INVALID_PARAMETER;
528 }
529
531
532 //
533 // If the event is not already signalled, do so
534 //
535
536 if (Event->SignalCount == 0x00000000) {
537 Event->SignalCount++;
538
539 //
540 // If signalling type is a notify function, queue it
541 //
542 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
543 if ((Event->ExFlag & EVT_EXFLAG_EVENT_GROUP) != 0) {
544 //
545 // The CreateEventEx() style requires all members of the Event Group
546 // to be signaled.
547 //
549 CoreNotifySignalList (&Event->EventGroup);
551 } else {
552 CoreNotifyEvent (Event);
553 }
554 }
555 }
556
558 return EFI_SUCCESS;
559}
560
572EFIAPI
574 IN EFI_EVENT UserEvent
575 )
576{
577 IEVENT *Event;
578 EFI_STATUS Status;
579
580 Event = UserEvent;
581
582 if (Event == NULL) {
583 return EFI_INVALID_PARAMETER;
584 }
585
586 if (Event->Signature != EVENT_SIGNATURE) {
587 return EFI_INVALID_PARAMETER;
588 }
589
590 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
591 return EFI_INVALID_PARAMETER;
592 }
593
594 Status = EFI_NOT_READY;
595
596 if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {
597 //
598 // Queue the wait notify function
599 //
601 if (Event->SignalCount == 0) {
602 CoreNotifyEvent (Event);
603 }
604
606 }
607
608 //
609 // If the even looks signalled, get the lock and clear it
610 //
611
612 if (Event->SignalCount != 0) {
614
615 if (Event->SignalCount != 0) {
616 Event->SignalCount = 0;
617 Status = EFI_SUCCESS;
618 }
619
621 }
622
623 return Status;
624}
625
641EFIAPI
643 IN UINTN NumberOfEvents,
644 IN EFI_EVENT *UserEvents,
645 OUT UINTN *UserIndex
646 )
647{
648 EFI_STATUS Status;
649 UINTN Index;
650
651 //
652 // Can only WaitForEvent at TPL_APPLICATION
653 //
654 if (gEfiCurrentTpl != TPL_APPLICATION) {
655 return EFI_UNSUPPORTED;
656 }
657
658 if (NumberOfEvents == 0) {
659 return EFI_INVALID_PARAMETER;
660 }
661
662 if (UserEvents == NULL) {
663 return EFI_INVALID_PARAMETER;
664 }
665
666 for ( ; ;) {
667 for (Index = 0; Index < NumberOfEvents; Index++) {
668 Status = CoreCheckEvent (UserEvents[Index]);
669
670 //
671 // provide index of event that caused problem
672 //
673 if (Status != EFI_NOT_READY) {
674 if (UserIndex != NULL) {
675 *UserIndex = Index;
676 }
677
678 return Status;
679 }
680 }
681
682 //
683 // Signal the Idle event
684 //
686 }
687}
688
699EFIAPI
701 IN EFI_EVENT UserEvent
702 )
703{
704 EFI_STATUS Status;
705 IEVENT *Event;
706
707 Event = UserEvent;
708
709 if (Event == NULL) {
710 return EFI_INVALID_PARAMETER;
711 }
712
713 if (Event->Signature != EVENT_SIGNATURE) {
714 return EFI_INVALID_PARAMETER;
715 }
716
717 //
718 // If it's a timer event, make sure it's not pending
719 //
720 if ((Event->Type & EVT_TIMER) != 0) {
721 CoreSetTimer (Event, TimerCancel, 0);
722 }
723
725
726 //
727 // If the event is queued somewhere, remove it
728 //
729
730 if (Event->RuntimeData.Link.ForwardLink != NULL) {
732 }
733
734 if (Event->NotifyLink.ForwardLink != NULL) {
735 RemoveEntryList (&Event->NotifyLink);
736 }
737
738 if (Event->SignalLink.ForwardLink != NULL) {
739 RemoveEntryList (&Event->SignalLink);
740 }
741
743
744 //
745 // If the event is registered on a protocol notify, then remove it from the protocol database
746 //
747 if ((Event->ExFlag & EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION) != 0) {
749 }
750
751 //
752 // To avoid the Event to be signalled wrongly after closed,
753 // clear the Signature of Event before free pool.
754 //
755 Event->Signature = 0;
756 Status = CoreFreePool (Event);
757 ASSERT_EFI_ERROR (Status);
758
759 return Status;
760}
UINT64 UINTN
INT64 INTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
Definition: BaseLib.h:2904
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
EFI_STATUS EFIAPI CoreSetTimer(IN EFI_EVENT UserEvent, IN EFI_TIMER_DELAY Type, IN UINT64 TriggerTime)
Definition: Timer.c:236
VOID CoreAcquireLock(IN EFI_LOCK *Lock)
Definition: Library.c:59
VOID CoreReleaseLock(IN EFI_LOCK *Lock)
Definition: Library.c:80
EFI_STATUS EFIAPI CoreFreePool(IN VOID *Buffer)
Definition: Pool.c:591
EFI_STATUS CoreUnregisterProtocolNotify(IN EFI_EVENT Event)
Definition: Handle.c:369
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID *EFIAPI AllocateRuntimeZeroPool(IN UINTN AllocationSize)
VOID CoreReleaseEventLock(VOID)
Definition: Event.c:106
EFI_STATUS CoreInitializeEventServices(VOID)
Definition: Event.c:120
LIST_ENTRY gEventSignalQueue
Definition: Event.c:36
UINT32 mEventTable[]
Definition: Event.c:41
LIST_ENTRY gEventQueue[TPL_HIGH_LEVEL+1]
Definition: Event.c:26
EFI_STATUS EFIAPI CoreCheckEvent(IN EFI_EVENT UserEvent)
Definition: Event.c:573
EFI_STATUS EFIAPI CoreCreateEventInternal(IN UINT32 Type, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN CONST VOID *NotifyContext OPTIONAL, IN CONST EFI_GUID *EventGroup OPTIONAL, OUT EFI_EVENT *Event)
Definition: Event.c:358
EFI_EVENT gIdleLoopEvent
Definition: Event.c:87
EFI_LOCK gEventQueueLock
Definition: Event.c:21
EFI_TPL gEfiCurrentTpl
Definition: Event.c:16
EFI_STATUS EFIAPI CoreSignalEvent(IN EFI_EVENT UserEvent)
Definition: Event.c:514
VOID CoreNotifySignalList(IN EFI_GUID *EventGroup)
Definition: Event.c:238
UINTN gEventPending
Definition: Event.c:31
EFI_STATUS EFIAPI CoreCreateEventEx(IN UINT32 Type, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN CONST VOID *NotifyContext OPTIONAL, IN CONST EFI_GUID *EventGroup OPTIONAL, OUT EFI_EVENT *Event)
Definition: Event.c:312
VOID CoreDispatchEventNotifies(IN EFI_TPL Priority)
Definition: Event.c:152
EFI_STATUS EFIAPI CoreCloseEvent(IN EFI_EVENT UserEvent)
Definition: Event.c:700
EFI_STATUS EFIAPI CoreWaitForEvent(IN UINTN NumberOfEvents, IN EFI_EVENT *UserEvents, OUT UINTN *UserIndex)
Definition: Event.c:642
VOID CoreAcquireEventLock(VOID)
Definition: Event.c:94
VOID CoreNotifyEvent(IN IEVENT *Event)
Definition: Event.c:205
EFI_STATUS EFIAPI CoreCreateEvent(IN UINT32 Type, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN VOID *NotifyContext OPTIONAL, OUT EFI_EVENT *Event)
Definition: Event.c:279
#define EVT_EXFLAG_EVENT_GROUP
Definition: Event.h:19
VOID CoreInitializeTimer(VOID)
Definition: Timer.c:162
#define EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION
Definition: Event.h:23
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
VOID EFIAPI NotifyFunction(IN EFI_EVENT Event, IN VOID *Context)
Definition: ScsiBus.c:1492
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define EFI_INITIALIZE_LOCK_VARIABLE(Priority)
Definition: UefiLib.h:313
VOID EFIAPI EfiEventEmptyFunction(IN EFI_EVENT Event, IN VOID *Context)
Definition: UefiLib.c:354
#define ASSERT_LOCKED(LockParameter)
Definition: UefiLib.h:331
VOID(EFIAPI * EFI_EVENT_NOTIFY)(IN EFI_EVENT Event, IN VOID *Context)
Definition: UefiSpec.h:463
@ TimerCancel
Definition: UefiSpec.h:531
EFI_LIST_ENTRY EventHead
A list of type EFI_RUNTIME_EVENT_ENTRY.
Definition: Runtime.h:109
EFI_EVENT_NOTIFY NotifyFunction
Definition: Runtime.h:81
EFI_LIST_ENTRY Link
Definition: Runtime.h:94
EFI_EVENT * Event
Definition: Runtime.h:89
Definition: Base.h:213
Definition: Event.h:39
EFI_RUNTIME_EVENT_ENTRY RuntimeData
Definition: Event.h:59
EFI_TPL NotifyTpl
Definition: Event.h:50
LIST_ENTRY SignalLink
Definition: Event.h:46