U
UEFI EVENT 的作用就是创建一个事件A,然后设定一个条件B,使得条件B满足的时候就执行这个事件A。条件B可以直接是EFI_BOOT_SERVICES.SignalEvent()这种直接调用事件A,也可以用EFI_BOOT_SERVICES.SetTimer()设定一个时间段后执行事件A,也可以是EFI_BOOT_SERVICES.RegisterProtocolNotify()在某个Protocol interface被install或者reinstall的时候执行事件A。
先我们看如何去创建一个事件。创建事件有两个函数CreateEvent()和CreateEventEx()。CreateEvent()只创建一个事件。后CreateEventEx()创建一个事件列表,最常用的就是创建ReadyToBootEvent 在启动OS之前处理某些事情。
我们先用个简单的例子来看看CreateEvent()的用法:
STATIC
VOID
EFIAPI
CHHEventTest (
IN EFI_EVENT Event,
IN VOID *Context
)
{
DEBUG ((EFI_D_INFO, "Charles EXE event ...\n"));
}
EFI_STATUS
EFIAPI
PlatformInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_EVENT mCHHEvent;
gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
CHHEventTest,
NULL,//This used to pass parameter to CHHEventTest
&mCHHEvent);
gBS->SetTimer (mCHHEvent, TimerRelative, 1 * 10 * 1000);
// gBS->SetTimer (mCHHEvent, TimerPeriodic, 1 * 10 * 1000);
DEBUG ((EFI_D_INFO, "Charles Event creat!\n"));
}
这里创建一个mCHHEvent 的事件,这个事件去调用了CHHEventTest这个函数,传递的参数为Null。这个mCHHEvent在1s之后被触发。关于TimerRelative这个参数,意思就是时间结束就触发事件如果是TimerPeriodic。那么这个mCHHEvent 会每隔1s被触发一次的循环下去。
下面我们看CreateEventEx()的用法,我们创建两个Event:mCHHEvent和mCHHEvent2,公用一个GUID gCHHEventExtestGuid。示例如下:
STATIC
VOID
EFIAPI
CHHEventTest (
IN EFI_EVENT Event,
IN VOID *Context
)
{
DEBUG ((EFI_D_INFO, "Charles CHHEventTest ...\n"));
}
STATIC
VOID
EFIAPI
CHHEventTest2 (
IN EFI_EVENT Event,
IN VOID *Context
)
{
DEBUG ((EFI_D_INFO, "Charles CHHEventTest2 ...\n"));
}
EFI_STATUS
EFIAPI
PlatformInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_EVENT mCHHEvent;
EFI_EVENT mCHHEvent2;
EFI_GUID gCHHEventExtestGuid = { 0x0579257E, 0x1843, 0x45FB, { 0x83, 0x9D, 0x6B, 0x79, 0x09, 0x38, 0x29, 0xA9 } };
gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
CHHEventTest,
NULL,
&gCHHEventExtestGuid,
&mCHHEvent
);
gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
CHHEventTest2,
NULL,
&gCHHEventExtestGuid,
&mCHHEvent2
);
DEBUG ((EFI_D_INFO, "Charles SignalEvent mCHHEvent ...\n"));
gBS->SignalEvent (mCHHEvent);
DEBUG ((EFI_D_INFO, "Charles SignalEvent mCHHEvent2 ...\n"));
gBS->SignalEvent (mCHHEvent2);
}
执行结果如下:
Charles SignalEvent mCHHEvent ...
Charles CHHEventTest2 ...
Charles CHHEventTest ...
Charles SignalEvent mCHHEvent2 ...
Charles CHHEventTest2 ...
Charles CHHEventTest ...
可以看出来,不管是Signal 同一个gCHHEventExtestGuid下面的任何一个Event,整个Event list 里面的Event都会被Signal。并且跟我们Signal的哪个Event 没有关系,同等TPL的后面的优先执行。那么我们改改不同TPL的看下,例如把mCHHEvent2的TPL降级为TPL_CALLBACK,执行结果如下:
Charles SignalEvent mCHHEvent ...
Charles CHHEventTest ...
Charles CHHEventTest2 ...
Charles SignalEvent mCHHEvent2 ...
Charles CHHEventTest ...
Charles CHHEventTest2 ...