/** @file\r
UEFI Event support functions implemented in this file.\r
\r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
EFI_TPL gEfiCurrentTpl = TPL_APPLICATION;\r
\r
///\r
-/// gEventQueueLock - Protects the event queus\r
+/// gEventQueueLock - Protects the event queues\r
///\r
EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);\r
\r
EVT_TIMER | EVT_NOTIFY_WAIT,\r
};\r
\r
+///\r
+/// gIdleLoopEvent - Event which is signalled when the core is idle\r
+///\r
+EFI_EVENT gIdleLoopEvent = NULL;\r
+\r
\r
/**\r
Enter critical section by acquiring the lock on gEventQueueLock.\r
\r
CoreInitializeTimer ();\r
\r
+ CoreCreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ EfiEventEmptyFunction,\r
+ NULL,\r
+ &gIdleLoopEventGuid,\r
+ &gIdleLoopEvent\r
+ );\r
+\r
return EFI_SUCCESS;\r
}\r
\r
// Only clear the SIGNAL status if it is a SIGNAL type event.\r
// WAIT type events are only cleared in CheckEvent()\r
//\r
- if (Event->Type & EVT_NOTIFY_SIGNAL) {\r
+ if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
Event->SignalCount = 0;\r
}\r
\r
CoreAcquireEventLock ();\r
}\r
\r
- gEventPending &= ~(1 << Priority);\r
+ gEventPending &= ~(UINTN)(1 << Priority);\r
CoreReleaseEventLock ();\r
}\r
\r
\r
\r
/**\r
- Creates a general-purpose event structure.\r
+ Creates an event.\r
\r
@param Type The type of event to create and its mode and\r
attributes\r
\r
\r
/**\r
- Creates a general-purpose event structure\r
+ Creates an event in a group.\r
\r
@param Type The type of event to create and its mode and\r
attributes\r
IN CONST EFI_GUID *EventGroup, OPTIONAL\r
OUT EFI_EVENT *Event\r
)\r
+{\r
+ //\r
+ // If it's a notify type of event, check for invalid NotifyTpl\r
+ //\r
+ if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
+ if (NotifyTpl != TPL_APPLICATION &&\r
+ NotifyTpl != TPL_CALLBACK &&\r
+ NotifyTpl != TPL_NOTIFY) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ return CoreCreateEventInternal (Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, Event);\r
+}\r
+\r
+/**\r
+ Creates a general-purpose event structure\r
+\r
+ @param Type The type of event to create and its mode and\r
+ attributes\r
+ @param NotifyTpl The task priority level of event notifications\r
+ @param NotifyFunction Pointer to the events notification function\r
+ @param NotifyContext Pointer to the notification functions context;\r
+ corresponds to parameter "Context" in the\r
+ notification function\r
+ @param EventGroup GUID for EventGroup if NULL act the same as\r
+ gBS->CreateEvent().\r
+ @param Event Pointer to the newly created event if the call\r
+ succeeds; undefined otherwise\r
+\r
+ @retval EFI_SUCCESS The event structure was created\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
+ @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreCreateEventInternal (\r
+ IN UINT32 Type,\r
+ IN EFI_TPL NotifyTpl,\r
+ IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL\r
+ IN CONST VOID *NotifyContext, OPTIONAL\r
+ IN CONST EFI_GUID *EventGroup, OPTIONAL\r
+ OUT EFI_EVENT *Event\r
+ )\r
{\r
EFI_STATUS Status;\r
IEVENT *IEvent;\r
}\r
\r
//\r
- // Allcoate and initialize a new event structure.\r
+ // Allocate and initialize a new event structure.\r
//\r
- Status = CoreAllocatePool (\r
- ((Type & EVT_RUNTIME) != 0) ? EfiRuntimeServicesData: EfiBootServicesData,\r
- sizeof (IEVENT),\r
- (VOID **)&IEvent\r
- );\r
- if (EFI_ERROR (Status)) {\r
+ if ((Type & EVT_RUNTIME) != 0) {\r
+ IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));\r
+ } else {\r
+ IEvent = AllocateZeroPool (sizeof (IEVENT));\r
+ }\r
+ if (IEvent == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- ZeroMem (IEvent, sizeof (IEVENT));\r
-\r
IEvent->Signature = EVENT_SIGNATURE;\r
IEvent->Type = Type;\r
\r
IEvent->NotifyContext = (VOID *)NotifyContext;\r
if (EventGroup != NULL) {\r
CopyGuid (&IEvent->EventGroup, EventGroup);\r
- IEvent->ExFlag = TRUE;\r
+ IEvent->ExFlag |= EVT_EXFLAG_EVENT_GROUP;\r
}\r
\r
*Event = IEvent;\r
//\r
// If signalling type is a notify function, queue it\r
//\r
- if (Event->Type & EVT_NOTIFY_SIGNAL) {\r
- if (Event->ExFlag) {\r
+ if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
+ if ((Event->ExFlag & EVT_EXFLAG_EVENT_GROUP) != 0) {\r
//\r
// The CreateEventEx() style requires all members of the Event Group\r
// to be signaled.\r
\r
Status = EFI_NOT_READY;\r
\r
- if (!Event->SignalCount && (Event->Type & EVT_NOTIFY_WAIT)) {\r
+ if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {\r
\r
//\r
// Queue the wait notify function\r
//\r
CoreAcquireEventLock ();\r
- if (!Event->SignalCount) {\r
+ if (Event->SignalCount == 0) {\r
CoreNotifyEvent (Event);\r
}\r
CoreReleaseEventLock ();\r
// If the even looks signalled, get the lock and clear it\r
//\r
\r
- if (Event->SignalCount) {\r
+ if (Event->SignalCount != 0) {\r
CoreAcquireEventLock ();\r
\r
- if (Event->SignalCount) {\r
+ if (Event->SignalCount != 0) {\r
Event->SignalCount = 0;\r
Status = EFI_SUCCESS;\r
}\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ if (NumberOfEvents == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (UserEvents == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
for(;;) {\r
\r
for(Index = 0; Index < NumberOfEvents; Index++) {\r
// provide index of event that caused problem\r
//\r
if (Status != EFI_NOT_READY) {\r
- *UserIndex = Index;\r
+ if (UserIndex != NULL) {\r
+ *UserIndex = Index;\r
+ }\r
return Status;\r
}\r
}\r
\r
//\r
- // This was the location of the Idle loop callback in EFI 1.x reference\r
- // code. We don't have that concept in this base at this point.\r
+ // Signal the Idle event\r
//\r
+ CoreSignalEvent (gIdleLoopEvent);\r
}\r
}\r
\r
//\r
// If the event is registered on a protocol notify, then remove it from the protocol database\r
//\r
- CoreUnregisterProtocolNotify (Event);\r
+ if ((Event->ExFlag & EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION) != 0) {\r
+ CoreUnregisterProtocolNotify (Event);\r
+ }\r
\r
+ //\r
+ // To avoid the Event to be signalled wrongly after closed,\r
+ // clear the Signature of Event before free pool.\r
+ //\r
+ Event->Signature = 0;\r
Status = CoreFreePool (Event);\r
ASSERT_EFI_ERROR (Status);\r
\r
return Status;\r
}\r
+\r