Updated minimal EFI Event support in userspace (#577)

This commit is contained in:
Pavel Naberezhnev 2025-10-01 10:48:41 +03:00 committed by GitHub
parent 849b04fdf4
commit 7897c1e039
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 378 additions and 291 deletions

1
.gitignore vendored
View File

@ -90,6 +90,7 @@ Utilities/TestProcessKernel/ProcessKernel
Utilities/TestNtfsDxe/TestNtfsDxe
Utilities/TestExt4Dxe/TestExt4Dxe
Utilities/TestFatDxe/TestFatDxe
Utilities/TestEvent/TestEvent
Utilities/LegacyBoot/ROOT*
Utilities/LegacyBoot/OpenCore*
Utilities/LegacyBoot/boot*

View File

@ -45,9 +45,9 @@ EFIAPI
UserCreateEventEx (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN CONST VOID *NotifyContext,
IN CONST EFI_GUID *EventGroup,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN CONST VOID *NotifyContext OPTIONAL,
IN CONST EFI_GUID *EventGroup OPTIONAL,
OUT EFI_EVENT *Event
);
@ -77,8 +77,8 @@ EFIAPI
UserCreateEvent (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN VOID *NotifyContext OPTIONAL,
OUT EFI_EVENT *Event
);

View File

@ -15,43 +15,52 @@
#include <time.h>
#endif
// Event Descriptor
struct USER_EVENT {
// It is unused descriptor?
/**
Event descriptor
IsClosed Is it an unused descriptor?
Signaled Is it a signaled event?
Type The type of Event
TplLevel The TPL Level of Event
NotifyFn A callback function
NotifyCtx A callback context
TimerEmit The timer trigger time
TimerDelta The timer triger delta
**/
typedef struct {
BOOLEAN IsClosed;
// Event is signaled?
BOOLEAN Signaled;
// Event type
UINT32 Type;
// Event TPL Level
EFI_TPL TplLevel;
// Callback function
EFI_EVENT_NOTIFY NotifyFn;
// Callback context
VOID *NotifyCtx;
// Timer trigger time
UINT64 TimerEmit;
// Timer trigger delta
UINT64 TimerDelta;
};
} USER_EVENT;
// for once init event subsystem
static BOOLEAN event_need_init = 1;
// current TPL level
static EFI_TPL CurTPL = 0;
// event descriptor's array
static struct USER_EVENT events[USER_EVENT_MAXNUM];
/**
Local variables
mEventNeedInit Do we need to initialize the event subsystem?
mCurTPL The current TPL value
mEvents The static array of Event descriptor
**/
STATIC BOOLEAN mEventNeedInit = TRUE;
STATIC EFI_TPL mCurTPL = 0;
STATIC USER_EVENT mEvents[USER_EVENT_MAXNUM];
/**
Returns current time in nanoseconds
**/
STATIC
UINT64
UserEventGetTimeNow (
VOID
)
{
UINT64 TimeNow = 0;
UINT64 TimeNow;
TimeNow = 0;
#if defined (_WIN32)
@ -65,47 +74,50 @@ UserEventGetTimeNow (
TimeNow = TimeNow*1000000000;
#elif defined (__MACH__)
clock_serv_t cclock;
mach_timespec_t now;
clock_serv_t Cclock;
mach_timespec_t Now;
host_get_clock_service (mach_host_self (), SYSTEM_CLOCK, &cclock);
clock_get_time (cclock, &now);
mach_port_deallocate (mach_task_self (), cclock);
host_get_clock_service (mach_host_self (), SYSTEM_CLOCK, &Cclock);
clock_get_time (Cclock, &Now);
mach_port_deallocate (mach_task_self (), Cclock);
TimeNow = (UINT64)now.tv_sec*1000000000 + now.tv_nsec;
TimeNow = (UINT64)Now.tv_sec*1000000000 + Now.tv_nsec;
#else
struct timespec now;
struct timespec Now;
clock_gettime (CLOCK_MONOTONIC, &now);
TimeNow = (UINT64)now.tv_sec*1000000000 + now.tv_nsec;
clock_gettime (CLOCK_MONOTONIC, &Now);
TimeNow = (UINT64)Now.tv_sec*1000000000 + Now.tv_nsec;
#endif
return TimeNow;
}
// event allocator
/**
Allocates an Event descriptor
**/
STATIC
struct USER_EVENT *
USER_EVENT *
UserEventAlloc (
VOID
)
{
struct USER_EVENT *res = NULL;
INTN Index;
for (INTN I = 0; I < USER_EVENT_MAXNUM; I++) {
if (events[I].IsClosed) {
events[I].IsClosed = 0;
res = &(events[I]);
break;
for (Index = 0; Index < USER_EVENT_MAXNUM; Index++) {
if (mEvents[Index].IsClosed == TRUE) {
mEvents[Index].IsClosed = 0;
return (&(mEvents[Index]));
}
}
return res;
return NULL;
}
// internal event dispatcher
/**
Dispatches signaled events and triggers active timers
**/
STATIC
VOID
UserEventDispatch (
@ -113,71 +125,97 @@ UserEventDispatch (
)
{
UINT64 TimeNow;
INTN Index;
TimeNow = UserEventGetTimeNow ();
for (INTN I = 0; I < USER_EVENT_MAXNUM; I++) {
if (events[I].IsClosed) {
// skip unused decriptors
for (Index = 0; Index < USER_EVENT_MAXNUM; Index++) {
if (mEvents[Index].IsClosed == TRUE) {
//
// Skip unused descriptors
//
continue;
}
// it is an active timer?
if ((events[I].Type & EVT_TIMER) && events[I].TimerEmit) {
if (TimeNow >= events[I].TimerEmit) {
// set signaled!
events[I].Signaled = 1;
//
// Is it an active timer?
//
if (((mEvents[Index].Type & EVT_TIMER) != 0) && (mEvents[Index].TimerEmit != 0)) {
if (TimeNow >= mEvents[Index].TimerEmit) {
//
// Signal Event
//
mEvents[Index].Signaled = TRUE;
// it is an periodic?
if (events[I].TimerDelta) {
// set new time for trigger
events[I].TimerEmit += events[I].TimerDelta;
//
// Is it a periodic timer?
//
if (mEvents[Index].TimerDelta != 0) {
//
// Update trigger time
//
mEvents[Index].TimerEmit += mEvents[Index].TimerDelta;
} else {
events[I].TimerEmit = 0;
mEvents[Index].TimerEmit = 0;
}
}
}
// signal?
if (events[I].Signaled && (events[I].Type & EVT_NOTIFY_SIGNAL)) {
// valid TPL?
if (CurTPL <= events[I].TplLevel) {
// clear state
events[I].Signaled = 0;
// emit handler
events[I].NotifyFn ((EFI_EVENT)&events[I], events[I].NotifyCtx);
//
// Is it a signaled event?
//
if ((mEvents[Index].Signaled == TRUE) && ((mEvents[Index].Type & EVT_NOTIFY_SIGNAL) != 0)) {
//
// Is TPL of Event valid?
//
if (mCurTPL <= mEvents[Index].TplLevel) {
//
// Reset state
//
mEvents[Index].Signaled = FALSE;
//
// Call handler
//
mEvents[Index].NotifyFn ((EFI_EVENT)&mEvents[Index], mEvents[Index].NotifyCtx);
}
}
}
}
// init event subsystem
/**
Inits the Event subsystem
**/
STATIC
VOID
UserEventInitializer (
VOID
)
{
for (INTN I = 0; I < USER_EVENT_MAXNUM; I++) {
// set unused state
events[I].IsClosed = 1;
events[I].TplLevel = 0;
events[I].TimerEmit = 0;
INTN Index;
for (Index = 0; Index < USER_EVENT_MAXNUM; Index++) {
mEvents[Index].IsClosed = TRUE;
mEvents[Index].TplLevel = 0;
mEvents[Index].TimerEmit = 0;
}
// init current TPL level
CurTPL = TPL_APPLICATION;
//
// Init current TPL
//
mCurTPL = TPL_APPLICATION;
}
// wrap around pthread_once() call
/**
Calls UserEventInitializer() if needed
**/
STATIC
VOID
UserEventInit (
VOID
)
{
if (event_need_init) {
event_need_init = 0;
if (mEventNeedInit == TRUE) {
mEventNeedInit = FALSE;
UserEventInitializer ();
}
}
@ -210,58 +248,66 @@ EFIAPI
UserCreateEventEx (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN CONST VOID *NotifyContext,
IN CONST EFI_GUID *EventGroup,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN CONST VOID *NotifyContext OPTIONAL,
IN CONST EFI_GUID *EventGroup OPTIONAL,
OUT EFI_EVENT *Event
)
{
struct USER_EVENT *ev = NULL;
USER_EVENT *Ev;
// init event subsystem
UserEventInit ();
// check input params
//
// Check input params
//
if (Event == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((Type & EVT_NOTIFY_SIGNAL) && (Type & EVT_NOTIFY_WAIT)) {
if (((Type & EVT_NOTIFY_SIGNAL) != 0) && ((Type & EVT_NOTIFY_WAIT) != 0)) {
//
// The Type param can't combine EVT_NOTIFY_SIGNAL and EVT_NOTIFY_WAIT flags
//
return EFI_INVALID_PARAMETER;
}
if (Type & (EVT_NOTIFY_SIGNAL | EVT_NOTIFY_WAIT)) {
// is signal or wait emit type
if ((Type & (EVT_NOTIFY_SIGNAL | EVT_NOTIFY_WAIT)) != 0) {
//
// Event type is signal or event
//
if (NotifyFunction == NULL) {
//
// callback function isn't set
//
return EFI_INVALID_PARAMETER;
}
if (!(NotifyTpl < USER_EVENT_MAXTPL)) {
// invalid required TPL
if (NotifyTpl >= USER_EVENT_MAXTPL) {
//
// Required TPL is invalid
//
return EFI_INVALID_PARAMETER;
}
}
// try alloc event descriptor
ev = UserEventAlloc ();
if (ev == NULL) {
// have no mem
//
// Try to allocate an Event descriptor
//
Ev = UserEventAlloc ();
if (Ev == NULL) {
*Event = NULL;
return EFI_OUT_OF_RESOURCES;
}
// set event descriptor fields
ev->Type = Type;
ev->TplLevel = NotifyTpl;
ev->Signaled = 0;
ev->NotifyFn = NotifyFunction;
ev->NotifyCtx = (VOID *)NotifyContext;
ev->TimerEmit = 0;
Ev->Type = Type;
Ev->TplLevel = NotifyTpl;
Ev->Signaled = 0;
Ev->NotifyFn = NotifyFunction;
Ev->NotifyCtx = (VOID *)NotifyContext;
Ev->TimerEmit = 0;
*Event = (EFI_EVENT)ev;
*Event = (EFI_EVENT)Ev;
return EFI_SUCCESS;
}
@ -291,8 +337,8 @@ EFIAPI
UserCreateEvent (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN VOID *NotifyContext OPTIONAL,
OUT EFI_EVENT *Event
)
{
@ -319,19 +365,17 @@ UserCloseEvent (
IN EFI_EVENT Event
)
{
struct USER_EVENT *ev = NULL;
USER_EVENT *Ev;
// init event subsystem
UserEventInit ();
ASSERT (Event != NULL);
// type cast
ev = (struct USER_EVENT *)Event;
// clear event state
ev->IsClosed = 1;
ev->TimerEmit = 0;
ev->TplLevel = 0;
Ev = (USER_EVENT *)Event;
Ev->IsClosed = TRUE;
Ev->TimerEmit = 0;
Ev->TplLevel = 0;
return EFI_SUCCESS;
}
@ -349,18 +393,17 @@ UserSignalEvent (
IN EFI_EVENT Event
)
{
struct USER_EVENT *ev = NULL;
USER_EVENT *Ev;
// init event subsystem
UserEventInit ();
ASSERT (Event != NULL);
ev = (struct USER_EVENT *)Event;
ASSERT (!(ev->IsClosed));
Ev = (USER_EVENT *)Event;
ASSERT (Ev->IsClosed == FALSE);
if (!(ev->IsClosed)) {
ev->Signaled = 1;
if (Ev->IsClosed == FALSE) {
Ev->Signaled = TRUE;
}
UserEventDispatch ();
@ -383,32 +426,35 @@ UserCheckEvent (
IN EFI_EVENT Event
)
{
struct USER_EVENT *ev = NULL;
EFI_STATUS Status;
USER_EVENT *Ev;
EFI_STATUS Status;
// init event subsystem
UserEventInit ();
ASSERT (Event != NULL);
ev = (struct USER_EVENT *)Event;
ASSERT (!(ev->IsClosed));
Ev = (USER_EVENT *)Event;
ASSERT (Ev->IsClosed == FALSE);
if (ev->Type & EVT_NOTIFY_SIGNAL) {
if ((Ev->Type & EVT_NOTIFY_SIGNAL) != 0) {
//
// The Event can't have the EVT_NOTIFY_SIGNAL type
//
return EFI_INVALID_PARAMETER;
}
UserEventDispatch ();
if (ev->Signaled) {
// Signaled?
ev->Signaled = 0;
if (Ev->Signaled == TRUE) {
Ev->Signaled = FALSE;
Status = EFI_SUCCESS;
} else {
// It isn't signaled event, but can be EVT_NOTIFY_WAIT type
// then we need emit callback function if TPL is valid
if ((ev->Type & EVT_NOTIFY_WAIT) && (CurTPL <= ev->TplLevel)) {
ev->NotifyFn ((EFI_EVENT)ev, ev->NotifyCtx);
//
// It isn't signaled event, but it can have the EVT_NOTIFY_WAIT type
// In that case, we need to emit callback function if TPL is valid
//
if (((Ev->Type & EVT_NOTIFY_WAIT) != 0) && (mCurTPL <= Ev->TplLevel)) {
Ev->NotifyFn ((EFI_EVENT)Ev, Ev->NotifyCtx);
}
Status = EFI_NOT_READY;
@ -438,58 +484,59 @@ UserWaitForEvent (
OUT UINTN *Index
)
{
struct USER_EVENT **evs = NULL;
struct USER_EVENT *ev = NULL;
USER_EVENT **Evs;
USER_EVENT *Ev;
UINTN Jndex;
UserEventInit ();
if (CurTPL != TPL_APPLICATION) {
if (mCurTPL != TPL_APPLICATION) {
return EFI_UNSUPPORTED;
}
ASSERT (Events != NULL);
ASSERT (Index != NULL);
evs = (struct USER_EVENT **)Events;
Evs = (USER_EVENT **)Events;
if (!NumberOfEvents) {
// check input param
if (NumberOfEvents == 0) {
return EFI_INVALID_PARAMETER;
}
WAIT_LOOP:
while (TRUE) {
//
// Blocking wait
//
UserEventDispatch ();
UserEventDispatch ();
for (UINTN I = 0; I < NumberOfEvents; I++) {
ev = evs[I];
for (Jndex = 0; Jndex < NumberOfEvents; Jndex++) {
Ev = Evs[Jndex];
if (ev == NULL) {
continue;
}
if (Ev == NULL) {
continue;
}
if (ev->IsClosed) {
continue;
}
if (Ev->IsClosed == TRUE) {
continue;
}
if (ev->Type & EVT_NOTIFY_SIGNAL) {
*Index = I;
return EFI_INVALID_PARAMETER;
}
if ((Ev->Type & EVT_NOTIFY_SIGNAL) != 0) {
*Index = Jndex;
return EFI_INVALID_PARAMETER;
}
if (ev->Signaled) {
*Index = I;
ev->Signaled = 0;
return EFI_SUCCESS;
} else {
if ((ev->Type & EVT_NOTIFY_WAIT) && (CurTPL <= ev->TplLevel)) {
ev->NotifyFn ((EFI_EVENT)ev, ev->NotifyCtx);
if (Ev->Signaled == TRUE) {
*Index = Jndex;
Ev->Signaled = FALSE;
return EFI_SUCCESS;
} else {
if (((Ev->Type & EVT_NOTIFY_WAIT) != 0) && (mCurTPL <= Ev->TplLevel)) {
Ev->NotifyFn ((EFI_EVENT)Ev, Ev->NotifyCtx);
}
}
}
}
// blocking wait
goto WAIT_LOOP;
}
/**
@ -512,17 +559,17 @@ UserSetTimer (
IN UINT64 TriggerTime
)
{
UINT64 TimeNow = 0;
struct USER_EVENT *ev = NULL;
UINT64 TimeNow;
USER_EVENT *Ev;
UserEventInit ();
// check input params
ASSERT (Event != NULL);
ev = (struct USER_EVENT *)Event;
ASSERT (!(ev->IsClosed));
Ev = (USER_EVENT *)Event;
ASSERT (Ev->IsClosed == FALSE);
if (!(ev->Type & EVT_TIMER)) {
if ((Ev->Type & EVT_TIMER) == 0) {
return EFI_INVALID_PARAMETER;
}
@ -530,17 +577,17 @@ UserSetTimer (
switch (Type) {
case TimerCancel:
ev->TimerEmit = 0;
Ev->TimerEmit = 0;
break;
case TimerRelative:
ev->TimerEmit = TimeNow + TriggerTime * 100;
ev->TimerDelta = 0;
Ev->TimerEmit = TimeNow + TriggerTime * 100;
Ev->TimerDelta = 0;
break;
case TimerPeriodic:
ev->TimerEmit = TimeNow + TriggerTime * 100;
ev->TimerDelta = TriggerTime * 100;
Ev->TimerEmit = TimeNow + TriggerTime * 100;
Ev->TimerDelta = TriggerTime * 100;
break;
default:
@ -565,18 +612,18 @@ UserRaiseTPL (
IN EFI_TPL NewTpl
)
{
EFI_TPL old;
EFI_TPL Old;
UserEventInit ();
UserEventDispatch ();
old = CurTPL;
if ((NewTpl >= old) && (NewTpl < USER_EVENT_MAXTPL)) {
CurTPL = NewTpl;
Old = mCurTPL;
if ((NewTpl >= Old) && (NewTpl < USER_EVENT_MAXTPL)) {
mCurTPL = NewTpl;
}
return old;
return Old;
}
/**
@ -591,10 +638,10 @@ UserRestoreTPL (
)
{
UserEventInit ();
ASSERT (OldTpl <= CurTPL);
ASSERT (OldTpl <= mCurTPL);
if (OldTpl < USER_EVENT_MAXTPL) {
CurTPL = OldTpl;
mCurTPL = OldTpl;
}
UserEventDispatch ();
@ -612,36 +659,38 @@ UserEventDispatchNow (
)
{
UINT64 TimeNow;
BOOLEAN res = FALSE;
BOOLEAN Res;
INTN Index;
UserEventInit ();
TimeNow = UserEventGetTimeNow ();
for (INTN I = 0; I < USER_EVENT_MAXNUM; I++) {
if (events[I].IsClosed) {
Res = FALSE;
for (Index = 0; Index < USER_EVENT_MAXNUM; Index++) {
if (mEvents[Index].IsClosed == TRUE) {
continue;
}
res = TRUE;
if ((events[I].Type & EVT_TIMER) && events[I].TimerEmit) {
if (TimeNow >= events[I].TimerEmit) {
events[I].Signaled = 1;
if (events[I].TimerDelta) {
events[I].TimerEmit += events[I].TimerDelta;
Res = TRUE;
if (((mEvents[Index].Type & EVT_TIMER) != 0) && (mEvents[Index].TimerEmit != 0)) {
if (TimeNow >= mEvents[Index].TimerEmit) {
mEvents[Index].Signaled = TRUE;
if (mEvents[Index].TimerDelta != 0) {
mEvents[Index].TimerEmit += mEvents[Index].TimerDelta;
} else {
events[I].TimerEmit = 0;
mEvents[Index].TimerEmit = 0;
}
}
}
if (events[I].Signaled && (events[I].Type & EVT_NOTIFY_SIGNAL)) {
if (CurTPL <= events[I].TplLevel) {
events[I].Signaled = 0;
events[I].NotifyFn ((EFI_EVENT)&events[I], events[I].NotifyCtx);
if ((mEvents[Index].Signaled == TRUE) && ((mEvents[Index].Type & EVT_NOTIFY_SIGNAL) != 0)) {
if (mCurTPL <= mEvents[Index].TplLevel) {
mEvents[Index].Signaled = FALSE;
mEvents[Index].NotifyFn ((EFI_EVENT)&mEvents[Index], mEvents[Index].NotifyCtx);
}
}
}
return res;
return Res;
}

View File

@ -5,116 +5,135 @@
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <stdio.h>
#include <unistd.h>
// context for callback functions
struct NOTIFY_CONTEXT1 {
/**
The context for callback functions
**/
typedef struct {
EFI_EVENT LinkedEvent;
UINTN Counter;
};
} NOTIFY_CONTEXT1;
// callback-functions for signal
/**
The callback function for a simple signal
**/
STATIC
VOID
SignalNotify1 (
IN EFI_EVENT Event,
IN VOID *Context
)
{
struct NOTIFY_CONTEXT1 *ctx = (struct NOTIFY_CONTEXT1 *)Context;
NOTIFY_CONTEXT1 *Ctx;
printf ("SignalNotify1()\n");
(ctx->Counter)++;
DEBUG ((DEBUG_INFO, "SignalNotify1()\n"));
Ctx = (NOTIFY_CONTEXT1 *)Context;
++(Ctx->Counter);
}
/**
The callback function for a self-destroy signal
**/
STATIC
VOID
SelfDestroyNotify1 (
IN EFI_EVENT Event,
IN VOID *Context
)
{
struct NOTIFY_CONTEXT1 *ctx = (struct NOTIFY_CONTEXT1 *)Context;
NOTIFY_CONTEXT1 *Ctx;
printf ("@@@@ SelfDestroyNotify1()\n");
(ctx->Counter)++;
DEBUG ((DEBUG_INFO, "@@@@ SelfDestroyNotify1()\n"));
Ctx = (NOTIFY_CONTEXT1 *)Context;
++(Ctx->Counter);
gBS->CloseEvent (Event);
}
/**
The callback function for linked signals
**/
STATIC
VOID
SignalNotify2 (
IN EFI_EVENT Event,
IN VOID *Context
)
{
struct NOTIFY_CONTEXT1 *ctx = (struct NOTIFY_CONTEXT1 *)Context;
EFI_STATUS Status;
NOTIFY_CONTEXT1 *Ctx;
// printf("SignalNotify2() %lu\n", ctx->Counter);
Status = gBS->SignalEvent (ctx->LinkedEvent);
// if (EFI_ERROR(Status)) {
// printf("SignalNotify2() %lu Error emited %d\n", ctx->Counter, Status);
// } else {
// printf("SignalNotify2() %lu Success Emited\n", ctx->Counter);
// }
(ctx->Counter)++;
Ctx = (NOTIFY_CONTEXT1 *)Context;
gBS->SignalEvent (Ctx->LinkedEvent);
++(Ctx->Counter);
}
/**
The callback function for a last-linked signal
**/
STATIC
VOID
SignalNotify3 (
IN EFI_EVENT Event,
IN VOID *Context
)
{
struct NOTIFY_CONTEXT1 *ctx = (struct NOTIFY_CONTEXT1 *)Context;
NOTIFY_CONTEXT1 *Ctx;
// printf("SignalNotify3() %lu\n", ctx->Counter);
(ctx->Counter)++;
Ctx = (NOTIFY_CONTEXT1 *)Context;
++(Ctx->Counter);
}
/**
The callback function for a linked wait signal
**/
STATIC
VOID
WaitNotify1 (
IN EFI_EVENT Event,
IN VOID *Context
)
{
struct NOTIFY_CONTEXT1 *ctx = (struct NOTIFY_CONTEXT1 *)Context;
EFI_STATUS Status;
NOTIFY_CONTEXT1 *Ctx;
// printf("WaitNotify1() %lu\n", ctx->Counter);
Status = gBS->SignalEvent (ctx->LinkedEvent);
// if (EFI_ERROR(Status)) {
// printf("WaitNotify1() %lu Error emited %d\n", ctx->Counter, Status);
// } else {
// printf("WaitNotify1() %lu Success Emited\n", ctx->Counter);
// }
(ctx->Counter)++;
Ctx = (NOTIFY_CONTEXT1 *)Context;
gBS->SignalEvent (Ctx->LinkedEvent);
++(Ctx->Counter);
}
int
main (
ENTRY_POINT (
VOID
)
{
EFI_STATUS Status;
struct NOTIFY_CONTEXT1 SignalNotifyContext1 = { 0, };
struct NOTIFY_CONTEXT1 SignalNotifyContext2 = { 0, };
struct NOTIFY_CONTEXT1 SignalNotifyContext3 = { 0, };
struct NOTIFY_CONTEXT1 WaitNotifyContext1 = { 0, };
struct NOTIFY_CONTEXT1 SelfDestroyContext1 = { 0, };
EFI_EVENT Signal1;
EFI_EVENT Signal2;
EFI_EVENT Signal3;
EFI_EVENT Wait1;
EFI_EVENT Timer1;
EFI_EVENT SelfD1;
UINTN TimerCounter1 = 0;
UINTN Index;
EFI_STATUS Status;
NOTIFY_CONTEXT1 SignalNotifyContext1 = { 0, };
NOTIFY_CONTEXT1 SignalNotifyContext2 = { 0, };
NOTIFY_CONTEXT1 SignalNotifyContext3 = { 0, };
NOTIFY_CONTEXT1 WaitNotifyContext1 = { 0, };
NOTIFY_CONTEXT1 SelfDestroyContext1 = { 0, };
EFI_EVENT Signal1;
EFI_EVENT Signal2;
EFI_EVENT Signal3;
EFI_EVENT Wait1;
EFI_EVENT Timer1;
EFI_EVENT SelfD1;
UINTN TimerCounter1 = 0;
UINTN Index;
INTN Jndex;
EFI_TPL OriginalTPL;
//
// Array for waiting events
//
EFI_EVENT Events[2];
printf ("=== Test UEFI Event System ===\n");
DEBUG ((DEBUG_INFO, "=== Test UEFI Event System ===\n"));
// create events
//
// Create events
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
@ -124,9 +143,9 @@ main (
);
if (EFI_ERROR (Status) || (Signal1 == NULL)) {
printf ("FAIL: Signal1 event creation (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Signal1 event creation (Status: %r)\n", Status));
} else {
printf ("PASS: Signal1 event created\n");
DEBUG ((DEBUG_INFO, "PASS: Signal1 event created\n"));
}
Status = gBS->CreateEvent (
@ -138,9 +157,9 @@ main (
);
if (EFI_ERROR (Status) || (Signal2 == NULL)) {
printf ("FAIL: Signal2 event creation (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Signal2 event creation (Status: %r)\n", Status));
} else {
printf ("PASS: Signal2 event created\n");
DEBUG ((DEBUG_INFO, "PASS: Signal2 event created\n"));
}
Status = gBS->CreateEvent (
@ -152,9 +171,9 @@ main (
);
if (EFI_ERROR (Status) || (Signal3 == NULL)) {
printf ("FAIL: Signal3 event creation (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Signal3 event creation (Status: %r)\n", Status));
} else {
printf ("PASS: Signal3 event created\n");
DEBUG ((DEBUG_INFO, "PASS: Signal3 event created\n"));
}
Status = gBS->CreateEvent (
@ -166,9 +185,9 @@ main (
);
if (EFI_ERROR (Status) || (Wait1 == NULL)) {
printf ("FAIL: Wait1 event creation (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Wait1 event creation (Status: %r)\n", Status));
} else {
printf ("PASS: Wait1 event created\n");
DEBUG ((DEBUG_INFO, "PASS: Wait1 event created\n"));
}
Status = gBS->CreateEvent (
@ -180,9 +199,9 @@ main (
);
if (EFI_ERROR (Status) || (Timer1 == NULL)) {
printf ("FAIL: Timer1 event creation (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Timer1 event creation (Status: %r)\n", Status));
} else {
printf ("PASS: Timer1 event created\n");
DEBUG ((DEBUG_INFO, "PASS: Timer1 event created\n"));
}
Status = gBS->CreateEvent (
@ -194,94 +213,111 @@ main (
);
if (EFI_ERROR (Status) || (SelfD1 == NULL)) {
printf ("FAIL: SelfD1 event creation (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: SelfD1 event creation (Status: %r)\n", Status));
} else {
printf ("PASS: SelfD event created\n");
DEBUG ((DEBUG_INFO, "PASS: SelfD event created\n"));
}
// links events
// signal2 with signal3
//
// Link events
// Signal2 --> Signal3
// Wait1 --> Signal2
//
SignalNotifyContext2.LinkedEvent = Signal3;
// wait1 with signal 2
WaitNotifyContext1.LinkedEvent = Signal2;
WaitNotifyContext1.LinkedEvent = Signal2;
// try sets timers
//
// Try to set timers
//
Status = gBS->SetTimer (Wait1, TimerPeriodic, 100*10000);
if (EFI_ERROR (Status)) {
printf ("FAIL: Set timer for Wait1 (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Set timer for Wait1 (Status: %r)\n", Status));
} else {
printf ("PASS: Wait1 set to 100*10000 periodic\n");
DEBUG ((DEBUG_INFO, "PASS: Wait1 set to 100*10000 periodic\n"));
}
Status = gBS->SetTimer (Timer1, TimerPeriodic, 10*10000);
if (EFI_ERROR (Status)) {
printf ("FAIL: Set timer for Timer1 (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Set timer for Timer1 (Status: %r)\n", Status));
} else {
printf ("PASS: Timer1 set to 10*10000 periodic\n");
DEBUG ((DEBUG_INFO, "PASS: Timer1 set to 10*10000 periodic\n"));
}
Status = gBS->SetTimer (SelfD1, TimerRelative, 30*10000);
if (EFI_ERROR (Status)) {
printf ("FAIL: Set timer for SelfD1 (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "FAIL: Set timer for SelfD1 (Status: %r)\n", Status));
} else {
printf ("PASS: SelfD1 set to 30*10000 relative\n");
DEBUG ((DEBUG_INFO, "PASS: SelfD1 set to 30*10000 relative\n"));
}
// try emit signal1
//
// Try to emit Signal1
//
gBS->SignalEvent (Signal1);
// try wait events
EFI_EVENT Events[] = { Timer1, Wait1 };
//
// Try to wait events
//
Events[0] = Timer1;
Events[1] = Wait1;
for (int i = 0; i < 10; i++) {
for (Jndex = 0; Jndex < 10; Jndex++) {
Status = gBS->WaitForEvent (2, Events, &Index);
if (!EFI_ERROR (Status)) {
printf ("Event %lu triggered\n", Index);
DEBUG ((DEBUG_INFO, "Event %u triggered\n", Index));
if (Index == 0) {
printf ("PASS: Timer1 event wait succeeded\n");
DEBUG ((DEBUG_INFO, "PASS: Timer1 event wait succeeded\n"));
TimerCounter1++;
}
} else {
printf ("Event Error %lu (Status: %lu)\n", Index, Status);
DEBUG ((DEBUG_INFO, "Event Error %u (Status: %r)\n", Index, Status));
}
}
// try check event
//
// Try to check event
//
Status = gBS->CheckEvent (Signal1);
if (Status == EFI_SUCCESS) {
printf ("FAIL: Event check succeeded\n");
DEBUG ((DEBUG_INFO, "FAIL: Event check succeeded\n"));
} else {
printf ("PASS: Event check error (Status: %lu)\n", Status);
DEBUG ((DEBUG_INFO, "PASS: Event check error (Status: %r)\n", Status));
}
// TPL Test
EFI_TPL OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
//
// The TPL test
//
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
printf ("TPL raised from %lu to %d\n", OriginalTPL, TPL_HIGH_LEVEL);
DEBUG ((DEBUG_INFO, "TPL raised from %u to %d\n", OriginalTPL, TPL_HIGH_LEVEL));
gBS->SignalEvent (Signal1);
printf ("EVENT SIGANL1 NEED PRINTF AFTER THIS LINE:\n");
DEBUG ((DEBUG_INFO, "EVENT SIGANL1 NEED PRINTF AFTER THIS LINE:\n"));
gBS->RestoreTPL (OriginalTPL);
printf ("TPL restored to %lu\n", OriginalTPL);
DEBUG ((DEBUG_INFO, "TPL restored to %u\n", OriginalTPL));
// test close event
//
// Try to close event
//
gBS->CloseEvent (Signal1);
gBS->CloseEvent (Timer1);
// try signal closed event
//
// Try to signal a closed event. Need to trigger ASSERT()
//
// gBS->SignalEvent (Signal1);
printf ("\n=== Test Summary ===\n");
printf ("Signal1 callbacks: %ld\n", SignalNotifyContext1.Counter);
printf ("Signal2 callbacks: %ld\n", SignalNotifyContext2.Counter);
printf ("Signal3 callbacks: %ld\n", SignalNotifyContext3.Counter);
printf ("Wait1 callbacks: %ld\n", WaitNotifyContext1.Counter);
printf ("SelfD1 callbacks: %ld\n", SelfDestroyContext1.Counter);
printf ("Timer1 callbacks: %ld\n", TimerCounter1);
DEBUG ((DEBUG_INFO, "\n=== Test Summary ===\n"));
DEBUG ((DEBUG_INFO, "Signal1 callbacks: %u\n", SignalNotifyContext1.Counter));
DEBUG ((DEBUG_INFO, "Signal2 callbacks: %u\n", SignalNotifyContext2.Counter));
DEBUG ((DEBUG_INFO, "Signal3 callbacks: %u\n", SignalNotifyContext3.Counter));
DEBUG ((DEBUG_INFO, "Wait1 callbacks: %u\n", WaitNotifyContext1.Counter));
DEBUG ((DEBUG_INFO, "SelfD1 callbacks: %u\n", SelfDestroyContext1.Counter));
DEBUG ((DEBUG_INFO, "Timer1 callbacks: %u\n", TimerCounter1));
gBS->CloseEvent (Signal2);
gBS->CloseEvent (Signal3);

View File

@ -29,6 +29,7 @@ buildutil() {
"TestExt4Dxe"
"TestFatDxe"
"TestNtfsDxe"
"TestEvent"
"TestPeCoff"
"TestProcessKernel"
"TestRsaPreprocess"