event.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 823 行 · 第 1/2 页
C
823 行
CoreCreateEventEx (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
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;
}
EfiCommonLibSetMem (IEvent, sizeof (IEVENT), 0);
IEvent->Signature = EVENT_SIGNATURE;
IEvent->Type = Type;
IEvent->NotifyTpl = NotifyTpl;
IEvent->NotifyFunction = NotifyFunction;
IEvent->NotifyContext = (VOID *)NotifyContext;
if (EventGroup != NULL) {
EfiCommonLibCopyMem (&IEvent->EventGroup, (VOID*)EventGroup, sizeof (EFI_GUID));
IEvent->ExFlag = TRUE;
}
*Event = IEvent;
if (Type & EFI_EVENT_RUNTIME) {
//
// 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 = NotifyContext;
IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;
InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);
}
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_BOOTSERVICE
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_BOOTSERVICE
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_BOOTSERVICE
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_BOOTSERVICE
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->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
//
CoreUnregisterProtocolNotify (Event);
Status = CoreFreePool (Event);
ASSERT_EFI_ERROR (Status);
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?