X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FEvent%2FEvent.c;h=86ca369d56ffad1a9f728138e1b18bc38dfb9c06;hb=e06179889586c37101e2900e7f52be9f0da12cda;hp=e8d20c1161d344bfe8ce31757531682b6612b770;hpb=022c6d45ef78605c173023f53984e4dfaf7b11f4;p=mirror_edk2.git diff --git a/MdeModulePkg/Core/Dxe/Event/Event.c b/MdeModulePkg/Core/Dxe/Event/Event.c index e8d20c1161..86ca369d56 100644 --- a/MdeModulePkg/Core/Dxe/Event/Event.c +++ b/MdeModulePkg/Core/Dxe/Event/Event.c @@ -1,8 +1,9 @@ /** @file UEFI Event support functions implemented in this file. -Copyright (c) 2006 - 2008, Intel Corporation.
-All rights reserved. This program and the accompanying materials +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php @@ -13,54 +14,85 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ -#include +#include "DxeMain.h" +#include "Event.h" -// -// Enumerate the valid types -// +/// +/// 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() - // + /// + /// 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(). - // + /// + /// 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() - // + /// + /// 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() - // + /// + /// 0x00000200 Generic event with a notification function that + /// is queue when the event is signaled with SignalEvent() + /// EVT_NOTIFY_SIGNAL, - // - // 0x00000201 ExitBootServicesEvent. - // + /// + /// 0x00000201 ExitBootServicesEvent. + /// EVT_SIGNAL_EXIT_BOOT_SERVICES, - // - // 0x60000202 SetVirtualAddressMapEvent. - // + /// + /// 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 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() - // + /// + /// 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. @@ -90,7 +122,7 @@ CoreReleaseEventLock ( /** - Initializes "event" support and populates parts of the System and Runtime Table. + Initializes "event" support. @retval EFI_SUCCESS Always return success @@ -108,6 +140,15 @@ CoreInitializeEventServices ( CoreInitializeTimer (); + CoreCreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + EfiEventEmptyFunction, + NULL, + &gIdleLoopEventGuid, + &gIdleLoopEvent + ); + return EFI_SUCCESS; } @@ -146,7 +187,7 @@ CoreDispatchEventNotifies ( // 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) { + if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) { Event->SignalCount = 0; } @@ -164,7 +205,7 @@ CoreDispatchEventNotifies ( CoreAcquireEventLock (); } - gEventPending &= ~(1 << Priority); + gEventPending &= ~(UINTN)(1 << Priority); CoreReleaseEventLock (); } @@ -237,7 +278,7 @@ CoreNotifySignalList ( /** - Creates a general-purpose event structure. + Creates an event. @param Type The type of event to create and its mode and attributes @@ -270,7 +311,7 @@ CoreCreateEvent ( /** - Creates a general-purpose event structure + Creates an event in a group. @param Type The type of event to create and its mode and attributes @@ -299,13 +340,58 @@ CoreCreateEventEx ( 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) || (NotifyTpl == TPL_APPLICATION)) { + if (Event == NULL) { return EFI_INVALID_PARAMETER; } @@ -358,7 +444,7 @@ CoreCreateEventEx ( // Check for an invalid NotifyFunction or NotifyTpl // if ((NotifyFunction == NULL) || - (NotifyTpl < TPL_APPLICATION) || + (NotifyTpl <= TPL_APPLICATION) || (NotifyTpl >= TPL_HIGH_LEVEL)) { return EFI_INVALID_PARAMETER; } @@ -373,19 +459,17 @@ CoreCreateEventEx ( } // - // Allcoate and initialize a new event structure. + // Allocate and initialize a new event structure. // - Status = CoreAllocatePool ( - ((Type & EVT_RUNTIME) != 0) ? EfiRuntimeServicesData: EfiBootServicesData, - sizeof (IEVENT), - (VOID **)&IEvent - ); - if (EFI_ERROR (Status)) { + if ((Type & EVT_RUNTIME) != 0) { + IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT)); + } else { + IEvent = AllocateZeroPool (sizeof (IEVENT)); + } + if (IEvent == NULL) { return EFI_OUT_OF_RESOURCES; } - ZeroMem (IEvent, sizeof (IEVENT)); - IEvent->Signature = EVENT_SIGNATURE; IEvent->Type = Type; @@ -394,7 +478,7 @@ CoreCreateEventEx ( IEvent->NotifyContext = (VOID *)NotifyContext; if (EventGroup != NULL) { CopyGuid (&IEvent->EventGroup, EventGroup); - IEvent->ExFlag = TRUE; + IEvent->ExFlag |= EVT_EXFLAG_EVENT_GROUP; } *Event = IEvent; @@ -470,8 +554,8 @@ CoreSignalEvent ( // // If signalling type is a notify function, queue it // - if (Event->Type & EVT_NOTIFY_SIGNAL) { - if (Event->ExFlag) { + 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. @@ -526,13 +610,13 @@ CoreCheckEvent ( Status = EFI_NOT_READY; - if (!Event->SignalCount && (Event->Type & EVT_NOTIFY_WAIT)) { + if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) { // // Queue the wait notify function // CoreAcquireEventLock (); - if (!Event->SignalCount) { + if (Event->SignalCount == 0) { CoreNotifyEvent (Event); } CoreReleaseEventLock (); @@ -542,10 +626,10 @@ CoreCheckEvent ( // If the even looks signalled, get the lock and clear it // - if (Event->SignalCount) { + if (Event->SignalCount != 0) { CoreAcquireEventLock (); - if (Event->SignalCount) { + if (Event->SignalCount != 0) { Event->SignalCount = 0; Status = EFI_SUCCESS; } @@ -590,6 +674,14 @@ CoreWaitForEvent ( return EFI_UNSUPPORTED; } + if (NumberOfEvents == 0) { + return EFI_INVALID_PARAMETER; + } + + if (UserEvents == NULL) { + return EFI_INVALID_PARAMETER; + } + for(;;) { for(Index = 0; Index < NumberOfEvents; Index++) { @@ -600,15 +692,17 @@ CoreWaitForEvent ( // provide index of event that caused problem // if (Status != EFI_NOT_READY) { - *UserIndex = Index; + if (UserIndex != NULL) { + *UserIndex = Index; + } return Status; } } // - // This was the location of the Idle loop callback in EFI 1.x reference - // code. We don't have that concept in this base at this point. + // Signal the Idle event // + CoreSignalEvent (gIdleLoopEvent); } } @@ -671,10 +765,18 @@ CoreCloseEvent ( // // If the event is registered on a protocol notify, then remove it from the protocol database // - CoreUnregisterProtocolNotify (Event); + 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; } +