2. In Graphics.c, Memory Leak in Graphics Library, ConvertBmpToUgaBlt(). 3. In HobLib.c, PeiBuildHobModule and three other functions do not zero hob reserved data area according to HOB spec v0.9. 4. In statuscode.h, the number of definition of EFI_SW_PEIM_PC_CAPSULE_START is equal to EFI_SW_PEIM_PC_CAPSULE_LOAD. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1861 6f19259b-4bc3-4df7-8a09-765794883524
863 lines
18 KiB
C
863 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) 2006, Intel Corporation
|
|
All rights reserved. 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
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
Module Name:
|
|
|
|
event.c
|
|
|
|
Abstract:
|
|
|
|
EFI Event support
|
|
|
|
--*/
|
|
|
|
|
|
#include <DxeMain.h>
|
|
|
|
//
|
|
// Enumerate the valid types
|
|
//
|
|
UINT32 mEventTable[] = {
|
|
//
|
|
// 0x80000200 Timer event with a notification function that is
|
|
// queue when the event is signaled with SignalEvent()
|
|
//
|
|
EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
|
|
//
|
|
// 0x80000000 Timer event without a notification function. It can be
|
|
// signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().
|
|
//
|
|
EFI_EVENT_TIMER,
|
|
//
|
|
// 0x00000100 Generic event with a notification function that
|
|
// can be waited on with CheckEvent() or WaitForEvent()
|
|
//
|
|
EFI_EVENT_NOTIFY_WAIT,
|
|
//
|
|
// 0x00000200 Generic event with a notification function that
|
|
// is queue when the event is signaled with SignalEvent()
|
|
//
|
|
EFI_EVENT_NOTIFY_SIGNAL,
|
|
//
|
|
// 0x00000201 ExitBootServicesEvent.
|
|
//
|
|
EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
|
|
//
|
|
// 0x60000202 SetVirtualAddressMapEvent.
|
|
//
|
|
EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
|
|
|
|
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
|
|
//
|
|
// 0x00000203 ReadyToBootEvent.
|
|
//
|
|
EFI_EVENT_SIGNAL_READY_TO_BOOT,
|
|
//
|
|
// 0x00000204 LegacyBootEvent.
|
|
//
|
|
EFI_EVENT_SIGNAL_LEGACY_BOOT,
|
|
//
|
|
// 0x00000603 Signal all ReadyToBootEvents.
|
|
//
|
|
EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_READY_TO_BOOT,
|
|
//
|
|
// 0x00000604 Signal all LegacyBootEvents.
|
|
//
|
|
EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_LEGACY_BOOT,
|
|
#endif
|
|
|
|
//
|
|
// 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()
|
|
//
|
|
EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_WAIT,
|
|
};
|
|
|
|
|
|
VOID
|
|
CoreAcquireEventLock (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enter critical section by acquiring the lock on gEventQueueLock.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CoreAcquireLock (&gEventQueueLock);
|
|
}
|
|
|
|
|
|
VOID
|
|
CoreReleaseEventLock (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Exit critical section by releasing the lock on gEventQueueLock.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CoreReleaseLock (&gEventQueueLock);
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
CoreInitializeEventServices (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes "event" support and populates parts of the System and Runtime Table.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - Always return success
|
|
|
|
--*/
|
|
{
|
|
UINTN Index;
|
|
|
|
for (Index=0; Index <= EFI_TPL_HIGH_LEVEL; Index++) {
|
|
InitializeListHead (&gEventQueue[Index]);
|
|
}
|
|
|
|
CoreInitializeTimer ();
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
CoreShutdownEventServices (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Register all runtime events to make sure they are still available after ExitBootService.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - Always return success.
|
|
|
|
--*/
|
|
{
|
|
LIST_ENTRY *Link;
|
|
IEVENT *Event;
|
|
|
|
//
|
|
// The Runtime AP is required for the core to function!
|
|
//
|
|
ASSERT (gRuntime != NULL);
|
|
|
|
for (Link = mRuntimeEventList.ForwardLink; Link != &mRuntimeEventList; Link = Link->ForwardLink) {
|
|
Event = CR (Link, IEVENT, RuntimeLink, EVENT_SIGNATURE);
|
|
gRuntime->RegisterEvent (
|
|
gRuntime,
|
|
Event->Type,
|
|
Event->NotifyTpl,
|
|
Event->NotifyFunction,
|
|
Event->NotifyContext,
|
|
(VOID **)Event
|
|
);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
CoreDispatchEventNotifies (
|
|
IN EFI_TPL Priority
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dispatches all pending events.
|
|
|
|
Arguments:
|
|
|
|
Priority - The task priority level of event notifications to dispatch
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
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 & EFI_EVENT_NOTIFY_SIGNAL) {
|
|
Event->SignalCount = 0;
|
|
}
|
|
|
|
CoreReleaseEventLock ();
|
|
|
|
//
|
|
// Notify this event
|
|
//
|
|
ASSERT (Event->NotifyFunction != NULL);
|
|
Event->NotifyFunction (Event, Event->NotifyContext);
|
|
|
|
//
|
|
// Check for next pending event
|
|
//
|
|
CoreAcquireEventLock ();
|
|
}
|
|
|
|
gEventPending &= ~(1 << Priority);
|
|
CoreReleaseEventLock ();
|
|
}
|
|
|
|
|
|
VOID
|
|
STATIC
|
|
CoreNotifyEvent (
|
|
IN IEVENT *Event
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Queues the event's notification function to fire
|
|
|
|
Arguments:
|
|
|
|
Event - The Event to notify
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
CoreNotifySignalList (
|
|
IN EFI_GUID *EventGroup
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Signals all events in the EventGroup
|
|
|
|
Arguments:
|
|
EventGroup - The list to signal
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
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 ();
|
|
}
|
|
|
|
|
|
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
|
|
|
|
static
|
|
VOID
|
|
EFIAPI
|
|
EventNotifySignalAllNullEvent (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
//
|
|
// This null event is a size efficent way to enusre that
|
|
// EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.
|
|
// EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into
|
|
// CreateEventEx() and this function is used to make the
|
|
// old error checking in CreateEvent() for Tiano extensions
|
|
// function.
|
|
//
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
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
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Creates a general-purpose event structure
|
|
|
|
Arguments:
|
|
Type - The type of event to create and its mode and attributes
|
|
NotifyTpl - The task priority level of event notifications
|
|
NotifyFunction - Pointer to the events notification function
|
|
NotifyContext - Pointer to the notification functions context; corresponds to
|
|
parameter "Context" in the notification function
|
|
Event - Pointer to the newly created event if the call succeeds; undefined otherwise
|
|
|
|
Returns:
|
|
EFI_SUCCESS - The event structure was created
|
|
EFI_INVALID_PARAMETER - One of the parameters has an invalid value
|
|
EFI_OUT_OF_RESOURCES - The event could not be allocated
|
|
|
|
--*/
|
|
{
|
|
EFI_GUID *GuidPtr;
|
|
EFI_EVENT_NOTIFY Function;
|
|
|
|
GuidPtr = NULL;
|
|
Function = NotifyFunction;
|
|
|
|
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
|
|
//
|
|
// Clear EFI_EVENT_NOFITY_SIGNAL_ALL (Tiano extension) as all events in the
|
|
// EventGroup now have this property. So we need to filter it out.
|
|
//
|
|
if (Type & EFI_EVENT_NOTIFY_SIGNAL_ALL) {
|
|
Type &= ~EFI_EVENT_NOTIFY_SIGNAL_ALL;
|
|
Function = EventNotifySignalAllNullEvent;
|
|
}
|
|
|
|
//
|
|
// Map the Tiano extensions Events to CreateEventEx form
|
|
//
|
|
if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) {
|
|
GuidPtr = &gEfiEventReadyToBootGuid;
|
|
} else if (Type == EFI_EVENT_SIGNAL_LEGACY_BOOT) {
|
|
GuidPtr = &gEfiEventLegacyBootGuid
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Convert EFI 1.10 Events to thier UEFI 2.0 CreateEventEx mapping
|
|
//
|
|
if (Type == EVENT_SIGNAL_EXIT_BOOT_SERVICES) {
|
|
GuidPtr = &gEfiEventExitBootServicesGuid;
|
|
} else if (Type == EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
|
|
GuidPtr = &gEfiEventVirtualAddressChangeGuid;
|
|
}
|
|
|
|
return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event);
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Creates a general-purpose event structure
|
|
|
|
Arguments:
|
|
Type - The type of event to create and its mode and attributes
|
|
NotifyTpl - The task priority level of event notifications
|
|
NotifyFunction - Pointer to the events notification function
|
|
NotifyContext - Pointer to the notification functions context; corresponds to
|
|
parameter "Context" in the notification function
|
|
EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent().
|
|
Event - Pointer to the newly created event if the call succeeds; undefined otherwise
|
|
|
|
Returns:
|
|
EFI_SUCCESS - The event structure was created
|
|
EFI_INVALID_PARAMETER - One of the parameters has an invalid value
|
|
EFI_OUT_OF_RESOURCES - The event could not be allocated
|
|
|
|
--*/
|
|
{
|
|
EFI_STATUS Status;
|
|
IEVENT *IEvent;
|
|
INTN Index;
|
|
|
|
|
|
if ((Event == NULL) || (NotifyTpl == EFI_TPL_APPLICATION)) {
|
|
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;
|
|
}
|
|
|
|
//
|
|
// If it's a notify type of event, check its parameters
|
|
//
|
|
if ((Type & (EFI_EVENT_NOTIFY_WAIT | EFI_EVENT_NOTIFY_SIGNAL))) {
|
|
//
|
|
// Check for an invalid NotifyFunction or NotifyTpl
|
|
//
|
|
if ((NotifyFunction == NULL) ||
|
|
(NotifyTpl < EFI_TPL_APPLICATION) ||
|
|
(NotifyTpl >= EFI_TPL_HIGH_LEVEL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// No notification needed, zero ignored values
|
|
//
|
|
NotifyTpl = 0;
|
|
NotifyFunction = NULL;
|
|
NotifyContext = NULL;
|
|
}
|
|
|
|
//
|
|
// Allcoate and initialize a new event structure.
|
|
//
|
|
Status = CoreAllocatePool (
|
|
(Type & EFI_EVENT_RUNTIME) ? EfiRuntimeServicesData: EfiBootServicesData,
|
|
sizeof (IEVENT),
|
|
(VOID **)&IEvent
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
SetMem (IEvent, sizeof (IEVENT), 0);
|
|
|
|
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 = TRUE;
|
|
}
|
|
|
|
*Event = IEvent;
|
|
|
|
if (Type & EFI_EVENT_RUNTIME) {
|
|
//
|
|
// Keep a list of all RT events so we can tell the RT AP.
|
|
//
|
|
InsertTailList (&mRuntimeEventList, &IEvent->RuntimeLink);
|
|
}
|
|
|
|
CoreAcquireEventLock ();
|
|
|
|
if ((Type & EFI_EVENT_NOTIFY_SIGNAL) != 0x00000000) {
|
|
//
|
|
// The Event's NotifyFunction must be queued whenever the event is signaled
|
|
//
|
|
InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);
|
|
}
|
|
|
|
CoreReleaseEventLock ();
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CoreSignalEvent (
|
|
IN EFI_EVENT UserEvent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Signals the event. Queues the event to be notified if needed
|
|
|
|
Arguments:
|
|
|
|
UserEvent - The event to signal
|
|
|
|
Returns:
|
|
|
|
EFI_INVALID_PARAMETER - Parameters are not valid.
|
|
|
|
EFI_SUCCESS - The event was signaled.
|
|
|
|
--*/
|
|
{
|
|
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 & EFI_EVENT_NOTIFY_SIGNAL) {
|
|
if (Event->ExFlag) {
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CoreCheckEvent (
|
|
IN EFI_EVENT UserEvent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check the status of an event
|
|
|
|
Arguments:
|
|
|
|
UserEvent - The event to check
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - The event is in the signaled state
|
|
EFI_NOT_READY - The event is not in the signaled state
|
|
EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL
|
|
|
|
--*/
|
|
|
|
{
|
|
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 & EFI_EVENT_NOTIFY_SIGNAL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = EFI_NOT_READY;
|
|
|
|
if (!Event->SignalCount && (Event->Type & EFI_EVENT_NOTIFY_WAIT)) {
|
|
|
|
//
|
|
// Queue the wait notify function
|
|
//
|
|
|
|
CoreAcquireEventLock ();
|
|
if (!Event->SignalCount) {
|
|
CoreNotifyEvent (Event);
|
|
}
|
|
CoreReleaseEventLock ();
|
|
}
|
|
|
|
//
|
|
// If the even looks signalled, get the lock and clear it
|
|
//
|
|
|
|
if (Event->SignalCount) {
|
|
CoreAcquireEventLock ();
|
|
|
|
if (Event->SignalCount) {
|
|
Event->SignalCount = 0;
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
CoreReleaseEventLock ();
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CoreWaitForEvent (
|
|
IN UINTN NumberOfEvents,
|
|
IN EFI_EVENT *UserEvents,
|
|
OUT UINTN *UserIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Stops execution until an event is signaled.
|
|
|
|
Arguments:
|
|
|
|
NumberOfEvents - The number of events in the UserEvents array
|
|
UserEvents - An array of EFI_EVENT
|
|
UserIndex - Pointer to the index of the event which satisfied the wait condition
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - The event indicated by Index was signaled.
|
|
EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or
|
|
Event was not a valid type
|
|
EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION
|
|
|
|
--*/
|
|
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Can only WaitForEvent at TPL_APPLICATION
|
|
//
|
|
if (gEfiCurrentTpl != EFI_TPL_APPLICATION) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
for(;;) {
|
|
|
|
for(Index = 0; Index < NumberOfEvents; Index++) {
|
|
|
|
Status = CoreCheckEvent (UserEvents[Index]);
|
|
|
|
//
|
|
// provide index of event that caused problem
|
|
//
|
|
if (Status != EFI_NOT_READY) {
|
|
*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.
|
|
//
|
|
}
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CoreCloseEvent (
|
|
IN EFI_EVENT UserEvent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Closes an event and frees the event structure.
|
|
|
|
Arguments:
|
|
|
|
UserEvent - Event to close
|
|
|
|
Returns:
|
|
|
|
EFI_INVALID_PARAMETER - Parameters are not valid.
|
|
|
|
EFI_SUCCESS - The event has been closed
|
|
|
|
--*/
|
|
|
|
{
|
|
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 & EFI_EVENT_TIMER) {
|
|
CoreSetTimer (Event, TimerCancel, 0);
|
|
}
|
|
|
|
CoreAcquireEventLock ();
|
|
|
|
//
|
|
// If the event is queued somewhere, remove it
|
|
//
|
|
|
|
if (Event->RuntimeLink.ForwardLink != NULL) {
|
|
RemoveEntryList (&Event->RuntimeLink);
|
|
}
|
|
|
|
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
|
|
//
|
|
CoreUnregisterProtocolNotify (Event);
|
|
|
|
Status = CoreFreePool (Event);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return Status;
|
|
}
|