diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Core/Dxe/Event | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Core/Dxe/Event')
| -rw-r--r-- | MdeModulePkg/Core/Dxe/Event/Event.c | 1520 | ||||
| -rw-r--r-- | MdeModulePkg/Core/Dxe/Event/Event.h | 176 | ||||
| -rw-r--r-- | MdeModulePkg/Core/Dxe/Event/Timer.c | 582 | ||||
| -rw-r--r-- | MdeModulePkg/Core/Dxe/Event/Tpl.c | 298 |
4 files changed, 1288 insertions, 1288 deletions
diff --git a/MdeModulePkg/Core/Dxe/Event/Event.c b/MdeModulePkg/Core/Dxe/Event/Event.c index dc82abb021..21f562ea95 100644 --- a/MdeModulePkg/Core/Dxe/Event/Event.c +++ b/MdeModulePkg/Core/Dxe/Event/Event.c @@ -1,760 +1,760 @@ -/** @file
- UEFI Event support functions implemented in this file.
-
-Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-#include "Event.h"
-
-///
-/// gEfiCurrentTpl - Current Task priority level
-///
-EFI_TPL gEfiCurrentTpl = TPL_APPLICATION;
-
-///
-/// gEventQueueLock - Protects the event queues
-///
-EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);
-
-///
-/// gEventQueue - A list of event's to notify for each priority level
-///
-LIST_ENTRY gEventQueue[TPL_HIGH_LEVEL + 1];
-
-///
-/// gEventPending - A bitmask of the EventQueues that are pending
-///
-UINTN gEventPending = 0;
-
-///
-/// gEventSignalQueue - A list of events to signal based on EventGroup type
-///
-LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue);
-
-///
-/// Enumerate the valid types
-///
-UINT32 mEventTable[] = {
- ///
- /// 0x80000200 Timer event with a notification function that is
- /// queue when the event is signaled with SignalEvent()
- ///
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- ///
- /// 0x80000000 Timer event without a notification function. It can be
- /// signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().
- ///
- EVT_TIMER,
- ///
- /// 0x00000100 Generic event with a notification function that
- /// can be waited on with CheckEvent() or WaitForEvent()
- ///
- EVT_NOTIFY_WAIT,
- ///
- /// 0x00000200 Generic event with a notification function that
- /// is queue when the event is signaled with SignalEvent()
- ///
- EVT_NOTIFY_SIGNAL,
- ///
- /// 0x00000201 ExitBootServicesEvent.
- ///
- EVT_SIGNAL_EXIT_BOOT_SERVICES,
- ///
- /// 0x60000202 SetVirtualAddressMapEvent.
- ///
- EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
-
- ///
- /// 0x00000000 Generic event without a notification function.
- /// It can be signaled with SignalEvent() and checked with CheckEvent()
- /// or WaitForEvent().
- ///
- 0x00000000,
- ///
- /// 0x80000100 Timer event with a notification function that can be
- /// waited on with CheckEvent() or WaitForEvent()
- ///
- EVT_TIMER | EVT_NOTIFY_WAIT,
-};
-
-///
-/// gIdleLoopEvent - Event which is signalled when the core is idle
-///
-EFI_EVENT gIdleLoopEvent = NULL;
-
-/**
- Enter critical section by acquiring the lock on gEventQueueLock.
-
-**/
-VOID
-CoreAcquireEventLock (
- VOID
- )
-{
- CoreAcquireLock (&gEventQueueLock);
-}
-
-/**
- Exit critical section by releasing the lock on gEventQueueLock.
-
-**/
-VOID
-CoreReleaseEventLock (
- VOID
- )
-{
- CoreReleaseLock (&gEventQueueLock);
-}
-
-/**
- Initializes "event" support.
-
- @retval EFI_SUCCESS Always return success
-
-**/
-EFI_STATUS
-CoreInitializeEventServices (
- VOID
- )
-{
- UINTN Index;
-
- for (Index = 0; Index <= TPL_HIGH_LEVEL; Index++) {
- InitializeListHead (&gEventQueue[Index]);
- }
-
- CoreInitializeTimer ();
-
- CoreCreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- EfiEventEmptyFunction,
- NULL,
- &gIdleLoopEventGuid,
- &gIdleLoopEvent
- );
-
- return EFI_SUCCESS;
-}
-
-/**
- Dispatches all pending events.
-
- @param Priority The task priority level of event notifications
- to dispatch
-
-**/
-VOID
-CoreDispatchEventNotifies (
- IN EFI_TPL Priority
- )
-{
- IEVENT *Event;
- LIST_ENTRY *Head;
-
- CoreAcquireEventLock ();
- ASSERT (gEventQueueLock.OwnerTpl == Priority);
- Head = &gEventQueue[Priority];
-
- //
- // Dispatch all the pending notifications
- //
- while (!IsListEmpty (Head)) {
- Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);
- RemoveEntryList (&Event->NotifyLink);
-
- Event->NotifyLink.ForwardLink = NULL;
-
- //
- // Only clear the SIGNAL status if it is a SIGNAL type event.
- // WAIT type events are only cleared in CheckEvent()
- //
- if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
- Event->SignalCount = 0;
- }
-
- CoreReleaseEventLock ();
-
- //
- // Notify this event
- //
- ASSERT (Event->NotifyFunction != NULL);
- Event->NotifyFunction (Event, Event->NotifyContext);
-
- //
- // Check for next pending event
- //
- CoreAcquireEventLock ();
- }
-
- gEventPending &= ~(UINTN)(1 << Priority);
- CoreReleaseEventLock ();
-}
-
-/**
- Queues the event's notification function to fire.
-
- @param Event The Event to notify
-
-**/
-VOID
-CoreNotifyEvent (
- IN IEVENT *Event
- )
-{
- //
- // Event database must be locked
- //
- ASSERT_LOCKED (&gEventQueueLock);
-
- //
- // If the event is queued somewhere, remove it
- //
-
- if (Event->NotifyLink.ForwardLink != NULL) {
- RemoveEntryList (&Event->NotifyLink);
- Event->NotifyLink.ForwardLink = NULL;
- }
-
- //
- // Queue the event to the pending notification list
- //
-
- InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);
- gEventPending |= (UINTN)(1 << Event->NotifyTpl);
-}
-
-/**
- Signals all events in the EventGroup.
-
- @param EventGroup The list to signal
-
-**/
-VOID
-CoreNotifySignalList (
- IN EFI_GUID *EventGroup
- )
-{
- LIST_ENTRY *Link;
- LIST_ENTRY *Head;
- IEVENT *Event;
-
- CoreAcquireEventLock ();
-
- Head = &gEventSignalQueue;
- for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
- Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);
- if (CompareGuid (&Event->EventGroup, EventGroup)) {
- CoreNotifyEvent (Event);
- }
- }
-
- CoreReleaseEventLock ();
-}
-
-/**
- Creates an event.
-
- @param Type The type of event to create and its mode and
- attributes
- @param NotifyTpl The task priority level of event notifications
- @param NotifyFunction Pointer to the events notification function
- @param NotifyContext Pointer to the notification functions context;
- corresponds to parameter "Context" in the
- notification function
- @param Event Pointer to the newly created event if the call
- succeeds; undefined otherwise
-
- @retval EFI_SUCCESS The event structure was created
- @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
- @retval EFI_OUT_OF_RESOURCES The event could not be allocated
-
-**/
-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
- )
-{
- return CoreCreateEventEx (Type, NotifyTpl, NotifyFunction, NotifyContext, NULL, Event);
-}
-
-/**
- Creates an event in a group.
-
- @param Type The type of event to create and its mode and
- attributes
- @param NotifyTpl The task priority level of event notifications
- @param NotifyFunction Pointer to the events notification function
- @param NotifyContext Pointer to the notification functions context;
- corresponds to parameter "Context" in the
- notification function
- @param EventGroup GUID for EventGroup if NULL act the same as
- gBS->CreateEvent().
- @param Event Pointer to the newly created event if the call
- succeeds; undefined otherwise
-
- @retval EFI_SUCCESS The event structure was created
- @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
- @retval EFI_OUT_OF_RESOURCES The event could not be allocated
-
-**/
-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
- )
-{
- //
- // If it's a notify type of event, check for invalid NotifyTpl
- //
- if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {
- if ((NotifyTpl != TPL_APPLICATION) &&
- (NotifyTpl != TPL_CALLBACK) &&
- (NotifyTpl != TPL_NOTIFY))
- {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- return CoreCreateEventInternal (Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, Event);
-}
-
-/**
- Creates a general-purpose event structure
-
- @param Type The type of event to create and its mode and
- attributes
- @param NotifyTpl The task priority level of event notifications
- @param NotifyFunction Pointer to the events notification function
- @param NotifyContext Pointer to the notification functions context;
- corresponds to parameter "Context" in the
- notification function
- @param EventGroup GUID for EventGroup if NULL act the same as
- gBS->CreateEvent().
- @param Event Pointer to the newly created event if the call
- succeeds; undefined otherwise
-
- @retval EFI_SUCCESS The event structure was created
- @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
- @retval EFI_OUT_OF_RESOURCES The event could not be allocated
-
-**/
-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
- )
-{
- EFI_STATUS Status;
- IEVENT *IEvent;
- INTN Index;
-
- if (Event == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check to make sure no reserved flags are set
- //
- Status = EFI_INVALID_PARAMETER;
- for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
- if (Type == mEventTable[Index]) {
- Status = EFI_SUCCESS;
- break;
- }
- }
-
- if (EFI_ERROR (Status)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Convert Event type for pre-defined Event groups
- //
- if (EventGroup != NULL) {
- //
- // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
- // are not valid
- //
- if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {
- Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;
- } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {
- Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;
- }
- } else {
- //
- // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping
- //
- if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {
- EventGroup = &gEfiEventExitBootServicesGuid;
- } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
- EventGroup = &gEfiEventVirtualAddressChangeGuid;
- }
- }
-
- //
- // If it's a notify type of event, check its parameters
- //
- if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {
- //
- // Check for an invalid NotifyFunction or NotifyTpl
- //
- if ((NotifyFunction == NULL) ||
- (NotifyTpl <= TPL_APPLICATION) ||
- (NotifyTpl >= TPL_HIGH_LEVEL))
- {
- return EFI_INVALID_PARAMETER;
- }
- } else {
- //
- // No notification needed, zero ignored values
- //
- NotifyTpl = 0;
- NotifyFunction = NULL;
- NotifyContext = NULL;
- }
-
- //
- // Allocate and initialize a new event structure.
- //
- if ((Type & EVT_RUNTIME) != 0) {
- IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));
- } else {
- IEvent = AllocateZeroPool (sizeof (IEVENT));
- }
-
- if (IEvent == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- IEvent->Signature = EVENT_SIGNATURE;
- IEvent->Type = Type;
-
- IEvent->NotifyTpl = NotifyTpl;
- IEvent->NotifyFunction = NotifyFunction;
- IEvent->NotifyContext = (VOID *)NotifyContext;
- if (EventGroup != NULL) {
- CopyGuid (&IEvent->EventGroup, EventGroup);
- IEvent->ExFlag |= EVT_EXFLAG_EVENT_GROUP;
- }
-
- *Event = IEvent;
-
- if ((Type & EVT_RUNTIME) != 0) {
- //
- // Keep a list of all RT events so we can tell the RT AP.
- //
- IEvent->RuntimeData.Type = Type;
- IEvent->RuntimeData.NotifyTpl = NotifyTpl;
- IEvent->RuntimeData.NotifyFunction = NotifyFunction;
- IEvent->RuntimeData.NotifyContext = (VOID *)NotifyContext;
- //
- // Work around the bug in the Platform Init specification (v1.7), reported
- // as Mantis#2017: "EFI_RUNTIME_EVENT_ENTRY.Event" should have type
- // EFI_EVENT, not (EFI_EVENT*). The PI spec documents the field correctly
- // as "The EFI_EVENT returned by CreateEvent()", but the type of the field
- // doesn't match the natural language description. Therefore we need an
- // explicit cast here.
- //
- IEvent->RuntimeData.Event = (EFI_EVENT *)IEvent;
- InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);
- }
-
- CoreAcquireEventLock ();
-
- if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {
- //
- // The Event's NotifyFunction must be queued whenever the event is signaled
- //
- InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);
- }
-
- CoreReleaseEventLock ();
-
- //
- // Done
- //
- return EFI_SUCCESS;
-}
-
-/**
- Signals the event. Queues the event to be notified if needed.
-
- @param UserEvent The event to signal .
-
- @retval EFI_INVALID_PARAMETER Parameters are not valid.
- @retval EFI_SUCCESS The event was signaled.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreSignalEvent (
- IN EFI_EVENT UserEvent
- )
-{
- IEVENT *Event;
-
- Event = UserEvent;
-
- if (Event == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Event->Signature != EVENT_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- CoreAcquireEventLock ();
-
- //
- // If the event is not already signalled, do so
- //
-
- if (Event->SignalCount == 0x00000000) {
- Event->SignalCount++;
-
- //
- // If signalling type is a notify function, queue it
- //
- if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
- if ((Event->ExFlag & EVT_EXFLAG_EVENT_GROUP) != 0) {
- //
- // The CreateEventEx() style requires all members of the Event Group
- // to be signaled.
- //
- CoreReleaseEventLock ();
- CoreNotifySignalList (&Event->EventGroup);
- CoreAcquireEventLock ();
- } else {
- CoreNotifyEvent (Event);
- }
- }
- }
-
- CoreReleaseEventLock ();
- return EFI_SUCCESS;
-}
-
-/**
- Check the status of an event.
-
- @param UserEvent The event to check
-
- @retval EFI_SUCCESS The event is in the signaled state
- @retval EFI_NOT_READY The event is not in the signaled state
- @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL
-
-**/
-EFI_STATUS
-EFIAPI
-CoreCheckEvent (
- IN EFI_EVENT UserEvent
- )
-{
- IEVENT *Event;
- EFI_STATUS Status;
-
- Event = UserEvent;
-
- if (Event == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Event->Signature != EVENT_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = EFI_NOT_READY;
-
- if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {
- //
- // Queue the wait notify function
- //
- CoreAcquireEventLock ();
- if (Event->SignalCount == 0) {
- CoreNotifyEvent (Event);
- }
-
- CoreReleaseEventLock ();
- }
-
- //
- // If the even looks signalled, get the lock and clear it
- //
-
- if (Event->SignalCount != 0) {
- CoreAcquireEventLock ();
-
- if (Event->SignalCount != 0) {
- Event->SignalCount = 0;
- Status = EFI_SUCCESS;
- }
-
- CoreReleaseEventLock ();
- }
-
- return Status;
-}
-
-/**
- Stops execution until an event is signaled.
-
- @param NumberOfEvents The number of events in the UserEvents array
- @param UserEvents An array of EFI_EVENT
- @param UserIndex Pointer to the index of the event which
- satisfied the wait condition
-
- @retval EFI_SUCCESS The event indicated by Index was signaled.
- @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification
- function or Event was not a valid type
- @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION
-
-**/
-EFI_STATUS
-EFIAPI
-CoreWaitForEvent (
- IN UINTN NumberOfEvents,
- IN EFI_EVENT *UserEvents,
- OUT UINTN *UserIndex
- )
-{
- EFI_STATUS Status;
- UINTN Index;
-
- //
- // Can only WaitForEvent at TPL_APPLICATION
- //
- if (gEfiCurrentTpl != TPL_APPLICATION) {
- return EFI_UNSUPPORTED;
- }
-
- if (NumberOfEvents == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (UserEvents == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- for ( ; ;) {
- for (Index = 0; Index < NumberOfEvents; Index++) {
- Status = CoreCheckEvent (UserEvents[Index]);
-
- //
- // provide index of event that caused problem
- //
- if (Status != EFI_NOT_READY) {
- if (UserIndex != NULL) {
- *UserIndex = Index;
- }
-
- return Status;
- }
- }
-
- //
- // Signal the Idle event
- //
- CoreSignalEvent (gIdleLoopEvent);
- }
-}
-
-/**
- Closes an event and frees the event structure.
-
- @param UserEvent Event to close
-
- @retval EFI_INVALID_PARAMETER Parameters are not valid.
- @retval EFI_SUCCESS The event has been closed
-
-**/
-EFI_STATUS
-EFIAPI
-CoreCloseEvent (
- IN EFI_EVENT UserEvent
- )
-{
- EFI_STATUS Status;
- IEVENT *Event;
-
- Event = UserEvent;
-
- if (Event == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Event->Signature != EVENT_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // If it's a timer event, make sure it's not pending
- //
- if ((Event->Type & EVT_TIMER) != 0) {
- CoreSetTimer (Event, TimerCancel, 0);
- }
-
- CoreAcquireEventLock ();
-
- //
- // If the event is queued somewhere, remove it
- //
-
- if (Event->RuntimeData.Link.ForwardLink != NULL) {
- RemoveEntryList (&Event->RuntimeData.Link);
- }
-
- if (Event->NotifyLink.ForwardLink != NULL) {
- RemoveEntryList (&Event->NotifyLink);
- }
-
- if (Event->SignalLink.ForwardLink != NULL) {
- RemoveEntryList (&Event->SignalLink);
- }
-
- CoreReleaseEventLock ();
-
- //
- // If the event is registered on a protocol notify, then remove it from the protocol database
- //
- if ((Event->ExFlag & EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION) != 0) {
- CoreUnregisterProtocolNotify (Event);
- }
-
- //
- // To avoid the Event to be signalled wrongly after closed,
- // clear the Signature of Event before free pool.
- //
- Event->Signature = 0;
- Status = CoreFreePool (Event);
- ASSERT_EFI_ERROR (Status);
-
- return Status;
-}
+/** @file + UEFI Event support functions implemented in this file. + +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR> +(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "Event.h" + +/// +/// gEfiCurrentTpl - Current Task priority level +/// +EFI_TPL gEfiCurrentTpl = TPL_APPLICATION; + +/// +/// gEventQueueLock - Protects the event queues +/// +EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL); + +/// +/// gEventQueue - A list of event's to notify for each priority level +/// +LIST_ENTRY gEventQueue[TPL_HIGH_LEVEL + 1]; + +/// +/// gEventPending - A bitmask of the EventQueues that are pending +/// +UINTN gEventPending = 0; + +/// +/// gEventSignalQueue - A list of events to signal based on EventGroup type +/// +LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue); + +/// +/// Enumerate the valid types +/// +UINT32 mEventTable[] = { + /// + /// 0x80000200 Timer event with a notification function that is + /// queue when the event is signaled with SignalEvent() + /// + EVT_TIMER | EVT_NOTIFY_SIGNAL, + /// + /// 0x80000000 Timer event without a notification function. It can be + /// signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent(). + /// + EVT_TIMER, + /// + /// 0x00000100 Generic event with a notification function that + /// can be waited on with CheckEvent() or WaitForEvent() + /// + EVT_NOTIFY_WAIT, + /// + /// 0x00000200 Generic event with a notification function that + /// is queue when the event is signaled with SignalEvent() + /// + EVT_NOTIFY_SIGNAL, + /// + /// 0x00000201 ExitBootServicesEvent. + /// + EVT_SIGNAL_EXIT_BOOT_SERVICES, + /// + /// 0x60000202 SetVirtualAddressMapEvent. + /// + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + + /// + /// 0x00000000 Generic event without a notification function. + /// It can be signaled with SignalEvent() and checked with CheckEvent() + /// or WaitForEvent(). + /// + 0x00000000, + /// + /// 0x80000100 Timer event with a notification function that can be + /// waited on with CheckEvent() or WaitForEvent() + /// + EVT_TIMER | EVT_NOTIFY_WAIT, +}; + +/// +/// gIdleLoopEvent - Event which is signalled when the core is idle +/// +EFI_EVENT gIdleLoopEvent = NULL; + +/** + Enter critical section by acquiring the lock on gEventQueueLock. + +**/ +VOID +CoreAcquireEventLock ( + VOID + ) +{ + CoreAcquireLock (&gEventQueueLock); +} + +/** + Exit critical section by releasing the lock on gEventQueueLock. + +**/ +VOID +CoreReleaseEventLock ( + VOID + ) +{ + CoreReleaseLock (&gEventQueueLock); +} + +/** + Initializes "event" support. + + @retval EFI_SUCCESS Always return success + +**/ +EFI_STATUS +CoreInitializeEventServices ( + VOID + ) +{ + UINTN Index; + + for (Index = 0; Index <= TPL_HIGH_LEVEL; Index++) { + InitializeListHead (&gEventQueue[Index]); + } + + CoreInitializeTimer (); + + CoreCreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + EfiEventEmptyFunction, + NULL, + &gIdleLoopEventGuid, + &gIdleLoopEvent + ); + + return EFI_SUCCESS; +} + +/** + Dispatches all pending events. + + @param Priority The task priority level of event notifications + to dispatch + +**/ +VOID +CoreDispatchEventNotifies ( + IN EFI_TPL Priority + ) +{ + IEVENT *Event; + LIST_ENTRY *Head; + + CoreAcquireEventLock (); + ASSERT (gEventQueueLock.OwnerTpl == Priority); + Head = &gEventQueue[Priority]; + + // + // Dispatch all the pending notifications + // + while (!IsListEmpty (Head)) { + Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE); + RemoveEntryList (&Event->NotifyLink); + + Event->NotifyLink.ForwardLink = NULL; + + // + // Only clear the SIGNAL status if it is a SIGNAL type event. + // WAIT type events are only cleared in CheckEvent() + // + if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) { + Event->SignalCount = 0; + } + + CoreReleaseEventLock (); + + // + // Notify this event + // + ASSERT (Event->NotifyFunction != NULL); + Event->NotifyFunction (Event, Event->NotifyContext); + + // + // Check for next pending event + // + CoreAcquireEventLock (); + } + + gEventPending &= ~(UINTN)(1 << Priority); + CoreReleaseEventLock (); +} + +/** + Queues the event's notification function to fire. + + @param Event The Event to notify + +**/ +VOID +CoreNotifyEvent ( + IN IEVENT *Event + ) +{ + // + // Event database must be locked + // + ASSERT_LOCKED (&gEventQueueLock); + + // + // If the event is queued somewhere, remove it + // + + if (Event->NotifyLink.ForwardLink != NULL) { + RemoveEntryList (&Event->NotifyLink); + Event->NotifyLink.ForwardLink = NULL; + } + + // + // Queue the event to the pending notification list + // + + InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink); + gEventPending |= (UINTN)(1 << Event->NotifyTpl); +} + +/** + Signals all events in the EventGroup. + + @param EventGroup The list to signal + +**/ +VOID +CoreNotifySignalList ( + IN EFI_GUID *EventGroup + ) +{ + LIST_ENTRY *Link; + LIST_ENTRY *Head; + IEVENT *Event; + + CoreAcquireEventLock (); + + Head = &gEventSignalQueue; + for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { + Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE); + if (CompareGuid (&Event->EventGroup, EventGroup)) { + CoreNotifyEvent (Event); + } + } + + CoreReleaseEventLock (); +} + +/** + Creates an event. + + @param Type The type of event to create and its mode and + attributes + @param NotifyTpl The task priority level of event notifications + @param NotifyFunction Pointer to the events notification function + @param NotifyContext Pointer to the notification functions context; + corresponds to parameter "Context" in the + notification function + @param Event Pointer to the newly created event if the call + succeeds; undefined otherwise + + @retval EFI_SUCCESS The event structure was created + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + @retval EFI_OUT_OF_RESOURCES The event could not be allocated + +**/ +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 + ) +{ + return CoreCreateEventEx (Type, NotifyTpl, NotifyFunction, NotifyContext, NULL, Event); +} + +/** + Creates an event in a group. + + @param Type The type of event to create and its mode and + attributes + @param NotifyTpl The task priority level of event notifications + @param NotifyFunction Pointer to the events notification function + @param NotifyContext Pointer to the notification functions context; + corresponds to parameter "Context" in the + notification function + @param EventGroup GUID for EventGroup if NULL act the same as + gBS->CreateEvent(). + @param Event Pointer to the newly created event if the call + succeeds; undefined otherwise + + @retval EFI_SUCCESS The event structure was created + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + @retval EFI_OUT_OF_RESOURCES The event could not be allocated + +**/ +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 + ) +{ + // + // If it's a notify type of event, check for invalid NotifyTpl + // + if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) { + if ((NotifyTpl != TPL_APPLICATION) && + (NotifyTpl != TPL_CALLBACK) && + (NotifyTpl != TPL_NOTIFY)) + { + return EFI_INVALID_PARAMETER; + } + } + + return CoreCreateEventInternal (Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, Event); +} + +/** + Creates a general-purpose event structure + + @param Type The type of event to create and its mode and + attributes + @param NotifyTpl The task priority level of event notifications + @param NotifyFunction Pointer to the events notification function + @param NotifyContext Pointer to the notification functions context; + corresponds to parameter "Context" in the + notification function + @param EventGroup GUID for EventGroup if NULL act the same as + gBS->CreateEvent(). + @param Event Pointer to the newly created event if the call + succeeds; undefined otherwise + + @retval EFI_SUCCESS The event structure was created + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + @retval EFI_OUT_OF_RESOURCES The event could not be allocated + +**/ +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 + ) +{ + EFI_STATUS Status; + IEVENT *IEvent; + INTN Index; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to make sure no reserved flags are set + // + Status = EFI_INVALID_PARAMETER; + for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) { + if (Type == mEventTable[Index]) { + Status = EFI_SUCCESS; + break; + } + } + + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // Convert Event type for pre-defined Event groups + // + if (EventGroup != NULL) { + // + // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE + // are not valid + // + if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) { + return EFI_INVALID_PARAMETER; + } + + if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) { + Type = EVT_SIGNAL_EXIT_BOOT_SERVICES; + } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) { + Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE; + } + } else { + // + // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping + // + if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) { + EventGroup = &gEfiEventExitBootServicesGuid; + } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) { + EventGroup = &gEfiEventVirtualAddressChangeGuid; + } + } + + // + // If it's a notify type of event, check its parameters + // + if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) { + // + // Check for an invalid NotifyFunction or NotifyTpl + // + if ((NotifyFunction == NULL) || + (NotifyTpl <= TPL_APPLICATION) || + (NotifyTpl >= TPL_HIGH_LEVEL)) + { + return EFI_INVALID_PARAMETER; + } + } else { + // + // No notification needed, zero ignored values + // + NotifyTpl = 0; + NotifyFunction = NULL; + NotifyContext = NULL; + } + + // + // Allocate and initialize a new event structure. + // + if ((Type & EVT_RUNTIME) != 0) { + IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT)); + } else { + IEvent = AllocateZeroPool (sizeof (IEVENT)); + } + + if (IEvent == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + IEvent->Signature = EVENT_SIGNATURE; + IEvent->Type = Type; + + IEvent->NotifyTpl = NotifyTpl; + IEvent->NotifyFunction = NotifyFunction; + IEvent->NotifyContext = (VOID *)NotifyContext; + if (EventGroup != NULL) { + CopyGuid (&IEvent->EventGroup, EventGroup); + IEvent->ExFlag |= EVT_EXFLAG_EVENT_GROUP; + } + + *Event = IEvent; + + if ((Type & EVT_RUNTIME) != 0) { + // + // Keep a list of all RT events so we can tell the RT AP. + // + IEvent->RuntimeData.Type = Type; + IEvent->RuntimeData.NotifyTpl = NotifyTpl; + IEvent->RuntimeData.NotifyFunction = NotifyFunction; + IEvent->RuntimeData.NotifyContext = (VOID *)NotifyContext; + // + // Work around the bug in the Platform Init specification (v1.7), reported + // as Mantis#2017: "EFI_RUNTIME_EVENT_ENTRY.Event" should have type + // EFI_EVENT, not (EFI_EVENT*). The PI spec documents the field correctly + // as "The EFI_EVENT returned by CreateEvent()", but the type of the field + // doesn't match the natural language description. Therefore we need an + // explicit cast here. + // + IEvent->RuntimeData.Event = (EFI_EVENT *)IEvent; + InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link); + } + + CoreAcquireEventLock (); + + if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) { + // + // The Event's NotifyFunction must be queued whenever the event is signaled + // + InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink); + } + + CoreReleaseEventLock (); + + // + // Done + // + return EFI_SUCCESS; +} + +/** + Signals the event. Queues the event to be notified if needed. + + @param UserEvent The event to signal . + + @retval EFI_INVALID_PARAMETER Parameters are not valid. + @retval EFI_SUCCESS The event was signaled. + +**/ +EFI_STATUS +EFIAPI +CoreSignalEvent ( + IN EFI_EVENT UserEvent + ) +{ + IEVENT *Event; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireEventLock (); + + // + // If the event is not already signalled, do so + // + + if (Event->SignalCount == 0x00000000) { + Event->SignalCount++; + + // + // If signalling type is a notify function, queue it + // + if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) { + if ((Event->ExFlag & EVT_EXFLAG_EVENT_GROUP) != 0) { + // + // The CreateEventEx() style requires all members of the Event Group + // to be signaled. + // + CoreReleaseEventLock (); + CoreNotifySignalList (&Event->EventGroup); + CoreAcquireEventLock (); + } else { + CoreNotifyEvent (Event); + } + } + } + + CoreReleaseEventLock (); + return EFI_SUCCESS; +} + +/** + Check the status of an event. + + @param UserEvent The event to check + + @retval EFI_SUCCESS The event is in the signaled state + @retval EFI_NOT_READY The event is not in the signaled state + @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL + +**/ +EFI_STATUS +EFIAPI +CoreCheckEvent ( + IN EFI_EVENT UserEvent + ) +{ + IEVENT *Event; + EFI_STATUS Status; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_NOT_READY; + + if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) { + // + // Queue the wait notify function + // + CoreAcquireEventLock (); + if (Event->SignalCount == 0) { + CoreNotifyEvent (Event); + } + + CoreReleaseEventLock (); + } + + // + // If the even looks signalled, get the lock and clear it + // + + if (Event->SignalCount != 0) { + CoreAcquireEventLock (); + + if (Event->SignalCount != 0) { + Event->SignalCount = 0; + Status = EFI_SUCCESS; + } + + CoreReleaseEventLock (); + } + + return Status; +} + +/** + Stops execution until an event is signaled. + + @param NumberOfEvents The number of events in the UserEvents array + @param UserEvents An array of EFI_EVENT + @param UserIndex Pointer to the index of the event which + satisfied the wait condition + + @retval EFI_SUCCESS The event indicated by Index was signaled. + @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification + function or Event was not a valid type + @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION + +**/ +EFI_STATUS +EFIAPI +CoreWaitForEvent ( + IN UINTN NumberOfEvents, + IN EFI_EVENT *UserEvents, + OUT UINTN *UserIndex + ) +{ + EFI_STATUS Status; + UINTN Index; + + // + // Can only WaitForEvent at TPL_APPLICATION + // + if (gEfiCurrentTpl != TPL_APPLICATION) { + return EFI_UNSUPPORTED; + } + + if (NumberOfEvents == 0) { + return EFI_INVALID_PARAMETER; + } + + if (UserEvents == NULL) { + return EFI_INVALID_PARAMETER; + } + + for ( ; ;) { + for (Index = 0; Index < NumberOfEvents; Index++) { + Status = CoreCheckEvent (UserEvents[Index]); + + // + // provide index of event that caused problem + // + if (Status != EFI_NOT_READY) { + if (UserIndex != NULL) { + *UserIndex = Index; + } + + return Status; + } + } + + // + // Signal the Idle event + // + CoreSignalEvent (gIdleLoopEvent); + } +} + +/** + Closes an event and frees the event structure. + + @param UserEvent Event to close + + @retval EFI_INVALID_PARAMETER Parameters are not valid. + @retval EFI_SUCCESS The event has been closed + +**/ +EFI_STATUS +EFIAPI +CoreCloseEvent ( + IN EFI_EVENT UserEvent + ) +{ + EFI_STATUS Status; + IEVENT *Event; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + // + // If it's a timer event, make sure it's not pending + // + if ((Event->Type & EVT_TIMER) != 0) { + CoreSetTimer (Event, TimerCancel, 0); + } + + CoreAcquireEventLock (); + + // + // If the event is queued somewhere, remove it + // + + if (Event->RuntimeData.Link.ForwardLink != NULL) { + RemoveEntryList (&Event->RuntimeData.Link); + } + + if (Event->NotifyLink.ForwardLink != NULL) { + RemoveEntryList (&Event->NotifyLink); + } + + if (Event->SignalLink.ForwardLink != NULL) { + RemoveEntryList (&Event->SignalLink); + } + + CoreReleaseEventLock (); + + // + // If the event is registered on a protocol notify, then remove it from the protocol database + // + if ((Event->ExFlag & EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION) != 0) { + CoreUnregisterProtocolNotify (Event); + } + + // + // To avoid the Event to be signalled wrongly after closed, + // clear the Signature of Event before free pool. + // + Event->Signature = 0; + Status = CoreFreePool (Event); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/MdeModulePkg/Core/Dxe/Event/Event.h b/MdeModulePkg/Core/Dxe/Event/Event.h index 201b90b301..3c80149f68 100644 --- a/MdeModulePkg/Core/Dxe/Event/Event.h +++ b/MdeModulePkg/Core/Dxe/Event/Event.h @@ -1,88 +1,88 @@ -/** @file
- UEFI Event support functions and structure.
-
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __EVENT_H__
-#define __EVENT_H__
-
-#define VALID_TPL(a) ((a) <= TPL_HIGH_LEVEL)
-extern UINTN gEventPending;
-
-///
-/// Set if Event is part of an event group
-///
-#define EVT_EXFLAG_EVENT_GROUP 0x01
-///
-/// Set if Event is registered on a protocol notify
-///
-#define EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION 0x02
-
-//
-// EFI_EVENT
-//
-
-///
-/// Timer event information
-///
-typedef struct {
- LIST_ENTRY Link;
- UINT64 TriggerTime;
- UINT64 Period;
-} TIMER_EVENT_INFO;
-
-#define EVENT_SIGNATURE SIGNATURE_32('e','v','n','t')
-typedef struct {
- UINTN Signature;
- UINT32 Type;
- UINT32 SignalCount;
- ///
- /// Entry if the event is registered to be signalled
- ///
- LIST_ENTRY SignalLink;
- ///
- /// Notification information for this event
- ///
- EFI_TPL NotifyTpl;
- EFI_EVENT_NOTIFY NotifyFunction;
- VOID *NotifyContext;
- EFI_GUID EventGroup;
- LIST_ENTRY NotifyLink;
- UINT8 ExFlag;
- ///
- /// A list of all runtime events
- ///
- EFI_RUNTIME_EVENT_ENTRY RuntimeData;
- TIMER_EVENT_INFO Timer;
-} IEVENT;
-
-//
-// Internal prototypes
-//
-
-/**
- Dispatches all pending events.
-
- @param Priority The task priority level of event notifications
- to dispatch
-
-**/
-VOID
-CoreDispatchEventNotifies (
- IN EFI_TPL Priority
- );
-
-/**
- Initializes timer support.
-
-**/
-VOID
-CoreInitializeTimer (
- VOID
- );
-
-#endif
+/** @file + UEFI Event support functions and structure. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> +(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __EVENT_H__ +#define __EVENT_H__ + +#define VALID_TPL(a) ((a) <= TPL_HIGH_LEVEL) +extern UINTN gEventPending; + +/// +/// Set if Event is part of an event group +/// +#define EVT_EXFLAG_EVENT_GROUP 0x01 +/// +/// Set if Event is registered on a protocol notify +/// +#define EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION 0x02 + +// +// EFI_EVENT +// + +/// +/// Timer event information +/// +typedef struct { + LIST_ENTRY Link; + UINT64 TriggerTime; + UINT64 Period; +} TIMER_EVENT_INFO; + +#define EVENT_SIGNATURE SIGNATURE_32('e','v','n','t') +typedef struct { + UINTN Signature; + UINT32 Type; + UINT32 SignalCount; + /// + /// Entry if the event is registered to be signalled + /// + LIST_ENTRY SignalLink; + /// + /// Notification information for this event + /// + EFI_TPL NotifyTpl; + EFI_EVENT_NOTIFY NotifyFunction; + VOID *NotifyContext; + EFI_GUID EventGroup; + LIST_ENTRY NotifyLink; + UINT8 ExFlag; + /// + /// A list of all runtime events + /// + EFI_RUNTIME_EVENT_ENTRY RuntimeData; + TIMER_EVENT_INFO Timer; +} IEVENT; + +// +// Internal prototypes +// + +/** + Dispatches all pending events. + + @param Priority The task priority level of event notifications + to dispatch + +**/ +VOID +CoreDispatchEventNotifies ( + IN EFI_TPL Priority + ); + +/** + Initializes timer support. + +**/ +VOID +CoreInitializeTimer ( + VOID + ); + +#endif diff --git a/MdeModulePkg/Core/Dxe/Event/Timer.c b/MdeModulePkg/Core/Dxe/Event/Timer.c index 29e507c67c..59c839a4f1 100644 --- a/MdeModulePkg/Core/Dxe/Event/Timer.c +++ b/MdeModulePkg/Core/Dxe/Event/Timer.c @@ -1,291 +1,291 @@ -/** @file
- Core Timer Services
-
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-#include "Event.h"
-
-//
-// Internal data
-//
-
-LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList);
-EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL - 1);
-EFI_EVENT mEfiCheckTimerEvent = NULL;
-
-EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);
-UINT64 mEfiSystemTime = 0;
-
-//
-// Timer functions
-//
-
-/**
- Inserts the timer event.
-
- @param Event Points to the internal structure of timer event
- to be installed
-
-**/
-VOID
-CoreInsertEventTimer (
- IN IEVENT *Event
- )
-{
- UINT64 TriggerTime;
- LIST_ENTRY *Link;
- IEVENT *Event2;
-
- ASSERT_LOCKED (&mEfiTimerLock);
-
- //
- // Get the timer's trigger time
- //
- TriggerTime = Event->Timer.TriggerTime;
-
- //
- // Insert the timer into the timer database in assending sorted order
- //
- for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) {
- Event2 = CR (Link, IEVENT, Timer.Link, EVENT_SIGNATURE);
-
- if (Event2->Timer.TriggerTime > TriggerTime) {
- break;
- }
- }
-
- InsertTailList (Link, &Event->Timer.Link);
-}
-
-/**
- Returns the current system time.
-
- @return The current system time
-
-**/
-UINT64
-CoreCurrentSystemTime (
- VOID
- )
-{
- UINT64 SystemTime;
-
- CoreAcquireLock (&mEfiSystemTimeLock);
- SystemTime = mEfiSystemTime;
- CoreReleaseLock (&mEfiSystemTimeLock);
-
- return SystemTime;
-}
-
-/**
- Checks the sorted timer list against the current system time.
- Signals any expired event timer.
-
- @param CheckEvent Not used
- @param Context Not used
-
-**/
-VOID
-EFIAPI
-CoreCheckTimers (
- IN EFI_EVENT CheckEvent,
- IN VOID *Context
- )
-{
- UINT64 SystemTime;
- IEVENT *Event;
-
- //
- // Check the timer database for expired timers
- //
- CoreAcquireLock (&mEfiTimerLock);
- SystemTime = CoreCurrentSystemTime ();
-
- while (!IsListEmpty (&mEfiTimerList)) {
- Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE);
-
- //
- // If this timer is not expired, then we're done
- //
- if (Event->Timer.TriggerTime > SystemTime) {
- break;
- }
-
- //
- // Remove this timer from the timer queue
- //
-
- RemoveEntryList (&Event->Timer.Link);
- Event->Timer.Link.ForwardLink = NULL;
-
- //
- // Signal it
- //
- CoreSignalEvent (Event);
-
- //
- // If this is a periodic timer, set it
- //
- if (Event->Timer.Period != 0) {
- //
- // Compute the timers new trigger time
- //
- Event->Timer.TriggerTime = Event->Timer.TriggerTime + Event->Timer.Period;
-
- //
- // If that's before now, then reset the timer to start from now
- //
- if (Event->Timer.TriggerTime <= SystemTime) {
- Event->Timer.TriggerTime = SystemTime;
- CoreSignalEvent (mEfiCheckTimerEvent);
- }
-
- //
- // Add the timer
- //
- CoreInsertEventTimer (Event);
- }
- }
-
- CoreReleaseLock (&mEfiTimerLock);
-}
-
-/**
- Initializes timer support.
-
-**/
-VOID
-CoreInitializeTimer (
- VOID
- )
-{
- EFI_STATUS Status;
-
- Status = CoreCreateEventInternal (
- EVT_NOTIFY_SIGNAL,
- TPL_HIGH_LEVEL - 1,
- CoreCheckTimers,
- NULL,
- NULL,
- &mEfiCheckTimerEvent
- );
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
- Called by the platform code to process a tick.
-
- @param Duration The number of 100ns elapsed since the last call
- to TimerTick
-
-**/
-VOID
-EFIAPI
-CoreTimerTick (
- IN UINT64 Duration
- )
-{
- IEVENT *Event;
-
- //
- // Check runtiem flag in case there are ticks while exiting boot services
- //
- CoreAcquireLock (&mEfiSystemTimeLock);
-
- //
- // Update the system time
- //
- mEfiSystemTime += Duration;
-
- //
- // If the head of the list is expired, fire the timer event
- // to process it
- //
- if (!IsListEmpty (&mEfiTimerList)) {
- Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE);
-
- if (Event->Timer.TriggerTime <= mEfiSystemTime) {
- CoreSignalEvent (mEfiCheckTimerEvent);
- }
- }
-
- CoreReleaseLock (&mEfiSystemTimeLock);
-}
-
-/**
- Sets the type of timer and the trigger time for a timer event.
-
- @param UserEvent The timer event that is to be signaled at the
- specified time
- @param Type The type of time that is specified in
- TriggerTime
- @param TriggerTime The number of 100ns units until the timer
- expires
-
- @retval EFI_SUCCESS The event has been set to be signaled at the
- requested time
- @retval EFI_INVALID_PARAMETER Event or Type is not valid
-
-**/
-EFI_STATUS
-EFIAPI
-CoreSetTimer (
- IN EFI_EVENT UserEvent,
- IN EFI_TIMER_DELAY Type,
- IN UINT64 TriggerTime
- )
-{
- IEVENT *Event;
-
- Event = UserEvent;
-
- if (Event == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Event->Signature != EVENT_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (((UINT32)Type > TimerRelative) || ((Event->Type & EVT_TIMER) == 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CoreAcquireLock (&mEfiTimerLock);
-
- //
- // If the timer is queued to the timer database, remove it
- //
- if (Event->Timer.Link.ForwardLink != NULL) {
- RemoveEntryList (&Event->Timer.Link);
- Event->Timer.Link.ForwardLink = NULL;
- }
-
- Event->Timer.TriggerTime = 0;
- Event->Timer.Period = 0;
-
- if (Type != TimerCancel) {
- if (Type == TimerPeriodic) {
- if (TriggerTime == 0) {
- gTimer->GetTimerPeriod (gTimer, &TriggerTime);
- }
-
- Event->Timer.Period = TriggerTime;
- }
-
- Event->Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
- CoreInsertEventTimer (Event);
-
- if (TriggerTime == 0) {
- CoreSignalEvent (mEfiCheckTimerEvent);
- }
- }
-
- CoreReleaseLock (&mEfiTimerLock);
-
- return EFI_SUCCESS;
-}
+/** @file + Core Timer Services + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "Event.h" + +// +// Internal data +// + +LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList); +EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL - 1); +EFI_EVENT mEfiCheckTimerEvent = NULL; + +EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL); +UINT64 mEfiSystemTime = 0; + +// +// Timer functions +// + +/** + Inserts the timer event. + + @param Event Points to the internal structure of timer event + to be installed + +**/ +VOID +CoreInsertEventTimer ( + IN IEVENT *Event + ) +{ + UINT64 TriggerTime; + LIST_ENTRY *Link; + IEVENT *Event2; + + ASSERT_LOCKED (&mEfiTimerLock); + + // + // Get the timer's trigger time + // + TriggerTime = Event->Timer.TriggerTime; + + // + // Insert the timer into the timer database in assending sorted order + // + for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) { + Event2 = CR (Link, IEVENT, Timer.Link, EVENT_SIGNATURE); + + if (Event2->Timer.TriggerTime > TriggerTime) { + break; + } + } + + InsertTailList (Link, &Event->Timer.Link); +} + +/** + Returns the current system time. + + @return The current system time + +**/ +UINT64 +CoreCurrentSystemTime ( + VOID + ) +{ + UINT64 SystemTime; + + CoreAcquireLock (&mEfiSystemTimeLock); + SystemTime = mEfiSystemTime; + CoreReleaseLock (&mEfiSystemTimeLock); + + return SystemTime; +} + +/** + Checks the sorted timer list against the current system time. + Signals any expired event timer. + + @param CheckEvent Not used + @param Context Not used + +**/ +VOID +EFIAPI +CoreCheckTimers ( + IN EFI_EVENT CheckEvent, + IN VOID *Context + ) +{ + UINT64 SystemTime; + IEVENT *Event; + + // + // Check the timer database for expired timers + // + CoreAcquireLock (&mEfiTimerLock); + SystemTime = CoreCurrentSystemTime (); + + while (!IsListEmpty (&mEfiTimerList)) { + Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE); + + // + // If this timer is not expired, then we're done + // + if (Event->Timer.TriggerTime > SystemTime) { + break; + } + + // + // Remove this timer from the timer queue + // + + RemoveEntryList (&Event->Timer.Link); + Event->Timer.Link.ForwardLink = NULL; + + // + // Signal it + // + CoreSignalEvent (Event); + + // + // If this is a periodic timer, set it + // + if (Event->Timer.Period != 0) { + // + // Compute the timers new trigger time + // + Event->Timer.TriggerTime = Event->Timer.TriggerTime + Event->Timer.Period; + + // + // If that's before now, then reset the timer to start from now + // + if (Event->Timer.TriggerTime <= SystemTime) { + Event->Timer.TriggerTime = SystemTime; + CoreSignalEvent (mEfiCheckTimerEvent); + } + + // + // Add the timer + // + CoreInsertEventTimer (Event); + } + } + + CoreReleaseLock (&mEfiTimerLock); +} + +/** + Initializes timer support. + +**/ +VOID +CoreInitializeTimer ( + VOID + ) +{ + EFI_STATUS Status; + + Status = CoreCreateEventInternal ( + EVT_NOTIFY_SIGNAL, + TPL_HIGH_LEVEL - 1, + CoreCheckTimers, + NULL, + NULL, + &mEfiCheckTimerEvent + ); + ASSERT_EFI_ERROR (Status); +} + +/** + Called by the platform code to process a tick. + + @param Duration The number of 100ns elapsed since the last call + to TimerTick + +**/ +VOID +EFIAPI +CoreTimerTick ( + IN UINT64 Duration + ) +{ + IEVENT *Event; + + // + // Check runtiem flag in case there are ticks while exiting boot services + // + CoreAcquireLock (&mEfiSystemTimeLock); + + // + // Update the system time + // + mEfiSystemTime += Duration; + + // + // If the head of the list is expired, fire the timer event + // to process it + // + if (!IsListEmpty (&mEfiTimerList)) { + Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE); + + if (Event->Timer.TriggerTime <= mEfiSystemTime) { + CoreSignalEvent (mEfiCheckTimerEvent); + } + } + + CoreReleaseLock (&mEfiSystemTimeLock); +} + +/** + Sets the type of timer and the trigger time for a timer event. + + @param UserEvent The timer event that is to be signaled at the + specified time + @param Type The type of time that is specified in + TriggerTime + @param TriggerTime The number of 100ns units until the timer + expires + + @retval EFI_SUCCESS The event has been set to be signaled at the + requested time + @retval EFI_INVALID_PARAMETER Event or Type is not valid + +**/ +EFI_STATUS +EFIAPI +CoreSetTimer ( + IN EFI_EVENT UserEvent, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ) +{ + IEVENT *Event; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + if (((UINT32)Type > TimerRelative) || ((Event->Type & EVT_TIMER) == 0)) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireLock (&mEfiTimerLock); + + // + // If the timer is queued to the timer database, remove it + // + if (Event->Timer.Link.ForwardLink != NULL) { + RemoveEntryList (&Event->Timer.Link); + Event->Timer.Link.ForwardLink = NULL; + } + + Event->Timer.TriggerTime = 0; + Event->Timer.Period = 0; + + if (Type != TimerCancel) { + if (Type == TimerPeriodic) { + if (TriggerTime == 0) { + gTimer->GetTimerPeriod (gTimer, &TriggerTime); + } + + Event->Timer.Period = TriggerTime; + } + + Event->Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime; + CoreInsertEventTimer (Event); + + if (TriggerTime == 0) { + CoreSignalEvent (mEfiCheckTimerEvent); + } + } + + CoreReleaseLock (&mEfiTimerLock); + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/Dxe/Event/Tpl.c b/MdeModulePkg/Core/Dxe/Event/Tpl.c index b33f80573c..d7ef8eb970 100644 --- a/MdeModulePkg/Core/Dxe/Event/Tpl.c +++ b/MdeModulePkg/Core/Dxe/Event/Tpl.c @@ -1,149 +1,149 @@ -/** @file
- Task priority (TPL) functions.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-#include "Event.h"
-
-/**
- Set Interrupt State.
-
- @param Enable The state of enable or disable interrupt
-
-**/
-VOID
-CoreSetInterruptState (
- IN BOOLEAN Enable
- )
-{
- EFI_STATUS Status;
- BOOLEAN InSmm;
-
- if (gCpu == NULL) {
- return;
- }
-
- if (!Enable) {
- gCpu->DisableInterrupt (gCpu);
- return;
- }
-
- if (gSmmBase2 == NULL) {
- gCpu->EnableInterrupt (gCpu);
- return;
- }
-
- Status = gSmmBase2->InSmm (gSmmBase2, &InSmm);
- if (!EFI_ERROR (Status) && !InSmm) {
- gCpu->EnableInterrupt (gCpu);
- }
-}
-
-/**
- Raise the task priority level to the new level.
- High level is implemented by disabling processor interrupts.
-
- @param NewTpl New task priority level
-
- @return The previous task priority level
-
-**/
-EFI_TPL
-EFIAPI
-CoreRaiseTpl (
- IN EFI_TPL NewTpl
- )
-{
- EFI_TPL OldTpl;
-
- OldTpl = gEfiCurrentTpl;
- if (OldTpl > NewTpl) {
- DEBUG ((DEBUG_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > NewTpl(0x%x)\n", OldTpl, NewTpl));
- ASSERT (FALSE);
- }
-
- ASSERT (VALID_TPL (NewTpl));
-
- //
- // If raising to high level, disable interrupts
- //
- if ((NewTpl >= TPL_HIGH_LEVEL) && (OldTpl < TPL_HIGH_LEVEL)) {
- CoreSetInterruptState (FALSE);
- }
-
- //
- // Set the new value
- //
- gEfiCurrentTpl = NewTpl;
-
- return OldTpl;
-}
-
-/**
- Lowers the task priority to the previous value. If the new
- priority unmasks events at a higher priority, they are dispatched.
-
- @param NewTpl New, lower, task priority
-
-**/
-VOID
-EFIAPI
-CoreRestoreTpl (
- IN EFI_TPL NewTpl
- )
-{
- EFI_TPL OldTpl;
- EFI_TPL PendingTpl;
-
- OldTpl = gEfiCurrentTpl;
- if (NewTpl > OldTpl) {
- DEBUG ((DEBUG_ERROR, "FATAL ERROR - RestoreTpl with NewTpl(0x%x) > OldTpl(0x%x)\n", NewTpl, OldTpl));
- ASSERT (FALSE);
- }
-
- ASSERT (VALID_TPL (NewTpl));
-
- //
- // If lowering below HIGH_LEVEL, make sure
- // interrupts are enabled
- //
-
- if ((OldTpl >= TPL_HIGH_LEVEL) && (NewTpl < TPL_HIGH_LEVEL)) {
- gEfiCurrentTpl = TPL_HIGH_LEVEL;
- }
-
- //
- // Dispatch any pending events
- //
- while (gEventPending != 0) {
- PendingTpl = (UINTN)HighBitSet64 (gEventPending);
- if (PendingTpl <= NewTpl) {
- break;
- }
-
- gEfiCurrentTpl = PendingTpl;
- if (gEfiCurrentTpl < TPL_HIGH_LEVEL) {
- CoreSetInterruptState (TRUE);
- }
-
- CoreDispatchEventNotifies (gEfiCurrentTpl);
- }
-
- //
- // Set the new value
- //
-
- gEfiCurrentTpl = NewTpl;
-
- //
- // If lowering below HIGH_LEVEL, make sure
- // interrupts are enabled
- //
- if (gEfiCurrentTpl < TPL_HIGH_LEVEL) {
- CoreSetInterruptState (TRUE);
- }
-}
+/** @file + Task priority (TPL) functions. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "Event.h" + +/** + Set Interrupt State. + + @param Enable The state of enable or disable interrupt + +**/ +VOID +CoreSetInterruptState ( + IN BOOLEAN Enable + ) +{ + EFI_STATUS Status; + BOOLEAN InSmm; + + if (gCpu == NULL) { + return; + } + + if (!Enable) { + gCpu->DisableInterrupt (gCpu); + return; + } + + if (gSmmBase2 == NULL) { + gCpu->EnableInterrupt (gCpu); + return; + } + + Status = gSmmBase2->InSmm (gSmmBase2, &InSmm); + if (!EFI_ERROR (Status) && !InSmm) { + gCpu->EnableInterrupt (gCpu); + } +} + +/** + Raise the task priority level to the new level. + High level is implemented by disabling processor interrupts. + + @param NewTpl New task priority level + + @return The previous task priority level + +**/ +EFI_TPL +EFIAPI +CoreRaiseTpl ( + IN EFI_TPL NewTpl + ) +{ + EFI_TPL OldTpl; + + OldTpl = gEfiCurrentTpl; + if (OldTpl > NewTpl) { + DEBUG ((DEBUG_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > NewTpl(0x%x)\n", OldTpl, NewTpl)); + ASSERT (FALSE); + } + + ASSERT (VALID_TPL (NewTpl)); + + // + // If raising to high level, disable interrupts + // + if ((NewTpl >= TPL_HIGH_LEVEL) && (OldTpl < TPL_HIGH_LEVEL)) { + CoreSetInterruptState (FALSE); + } + + // + // Set the new value + // + gEfiCurrentTpl = NewTpl; + + return OldTpl; +} + +/** + Lowers the task priority to the previous value. If the new + priority unmasks events at a higher priority, they are dispatched. + + @param NewTpl New, lower, task priority + +**/ +VOID +EFIAPI +CoreRestoreTpl ( + IN EFI_TPL NewTpl + ) +{ + EFI_TPL OldTpl; + EFI_TPL PendingTpl; + + OldTpl = gEfiCurrentTpl; + if (NewTpl > OldTpl) { + DEBUG ((DEBUG_ERROR, "FATAL ERROR - RestoreTpl with NewTpl(0x%x) > OldTpl(0x%x)\n", NewTpl, OldTpl)); + ASSERT (FALSE); + } + + ASSERT (VALID_TPL (NewTpl)); + + // + // If lowering below HIGH_LEVEL, make sure + // interrupts are enabled + // + + if ((OldTpl >= TPL_HIGH_LEVEL) && (NewTpl < TPL_HIGH_LEVEL)) { + gEfiCurrentTpl = TPL_HIGH_LEVEL; + } + + // + // Dispatch any pending events + // + while (gEventPending != 0) { + PendingTpl = (UINTN)HighBitSet64 (gEventPending); + if (PendingTpl <= NewTpl) { + break; + } + + gEfiCurrentTpl = PendingTpl; + if (gEfiCurrentTpl < TPL_HIGH_LEVEL) { + CoreSetInterruptState (TRUE); + } + + CoreDispatchEventNotifies (gEfiCurrentTpl); + } + + // + // Set the new value + // + + gEfiCurrentTpl = NewTpl; + + // + // If lowering below HIGH_LEVEL, make sure + // interrupts are enabled + // + if (gEfiCurrentTpl < TPL_HIGH_LEVEL) { + CoreSetInterruptState (TRUE); + } +} |
