在进bios setup 之前,我们可以在屏幕上显示“Entering BIOS Setup
BIOS 以一秒为步长 周期性的打印到屏幕上。
这个就是用event 来实现的。
相关代码如下:
//
// Create a timer to indicate "Entering Setup".
//
IndicatorMessage = NULL;
IndicatorMessage = HiiGetString (mStringHiiHandle, STRING_TOKEN (STRING_SYSTEM_BIOS_SETUP_ENTERING_MSG), NULL);
DPRINTF (" maxwell maxwell start show IndicatorMessage = %s\n", IndicatorMessage);
gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
IndicatorMsg,
(VOID*)IndicatorMessage,
&TimerEvent);
gBS->SetTimer (TimerEvent, TimerPeriodic, 1 * 1000 * 1000);
函数gBS->CreateEvent 创建了TimerEvent。 然后将TimerEvent 传给 gBS->SetTimer, 注意SetTimer 的第二个参数TimerPeriodic, 表明这个事情将会被周期性的触发。
那接下来,引出一个问题, 上面事件每一秒跑一次, 什么时候截止呢?
顺着代码往下看,我们看到了如下三行代码:
//
// Stop the timer.
//
gBS->SetTimer (TimerEvent, TimerCancel, 0);
gBS->CloseEvent (TimerEvent);
TimerEvent = NULL;
}
第一行, 给SetTimer 传入TimerCancel, 表明这个事件会被取消
第二行CloseEvent , 将event 从链表上摘除,后续 谁也不能用它了。
第三行 指针 指向空,防止野指针。
接下来,对CreateEvent 和SetTimer 进行详细分析
/**
Sets the type of timer and the trigger time for a timer event.
@param UserEvent The timer event that is to be signaled at the
specified time
@param Type The type of time that is specified in
TriggerTime
@param TriggerTime The number of 100ns units until the timer
expires
@retval EFI_SUCCESS The event has been set to be signaled at the
requested time
@retval EFI_INVALID_PARAMETER Event or Type is not valid
**/
EFI_STATUS
EFIAPI
CoreSetTimer (
IN EFI_EVENT UserEvent,
IN EFI_TIMER_DELAY Type,
IN UINT64 TriggerTime
)
{
IEVENT *Event;
Event = UserEvent;
if (Event == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Event->Signature != EVENT_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
if ((UINT32)Type > TimerRelative || (Event->Type & EVT_TIMER) == 0) {
return EFI_INVALID_PARAMETER;
}
CoreAcquireLock (&mEfiTimerLock);
//
// If the timer is queued to the timer database, remove it
//
if (Event->Timer.Link.ForwardLink != NULL) {
RemoveEntryList (&Event->Timer.Link);
Event->Timer.Link.ForwardLink = NULL;
}
Event->Timer.TriggerTime = 0;
Event->Timer.Period = 0;
if (Type != TimerCancel) {
if (Type == TimerPeriodic) {
if (TriggerTime == 0) {
gTimer->GetTimerPeriod (gTimer, &TriggerTime);
}
Event->Timer.Period = TriggerTime;
}
Event->Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
CoreInsertEventTimer (Event);
if (TriggerTime == 0) {
CoreSignalEvent (mEfiCheckTimerEvent);
}
}
CoreReleaseLock (&mEfiTimerLock);
return EFI_SUCCESS;
}
如果参数不是TimerCancel , 将Event 插入链表里面 CoreInsertEventTimer (Event); 如果时间为0. 直接触发CoreSignalEvent (mEfiCheckTimerEvent);
/**
Initializes timer support.
**/
VOID
CoreInitializeTimer (
VOID
)
{
EFI_STATUS Status;
Status = CoreCreateEventInternal (
EVT_NOTIFY_SIGNAL,
TPL_HIGH_LEVEL - 1,
CoreCheckTimers,
NULL,
NULL,
&mEfiCheckTimerEvent
);
ASSERT_EFI_ERROR (Status);
}
CoreCheckTimers
函数实现如下:
/**
Checks the sorted timer list against the current system time.
Signals any expired event timer.
@param CheckEvent Not used
@param Context Not used
**/
VOID
EFIAPI
CoreCheckTimers (
IN EFI_EVENT CheckEvent,
IN VOID *Context
)
{
UINT64 SystemTime;
IEVENT *Event;
//
// Check the timer database for expired timers
//
CoreAcquireLock (&mEfiTimerLock);
SystemTime = CoreCurrentSystemTime ();
while (!IsListEmpty (&mEfiTimerList)) {
Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE);
//
// If this timer is not expired, then we're done
//
if (Event->Timer.TriggerTime > SystemTime) {
break;
}
//
// Remove this timer from the timer queue
//
RemoveEntryList (&Event->Timer.Link);
Event->Timer.Link.ForwardLink = NULL;
//
// Signal it
//
CoreSignalEvent (Event);
//
// If this is a periodic timer, set it
//
if (Event->Timer.Period != 0) {
//
// Compute the timers new trigger time
//
Event->Timer.TriggerTime = Event->Timer.TriggerTime + Event->Timer.Period;
//
// If that's before now, then reset the timer to start from now
//
if (Event->Timer.TriggerTime <= SystemTime) {
Event->Timer.TriggerTime = SystemTime;
CoreSignalEvent (mEfiCheckTimerEvent);
}
//
// Add the timer
//
CoreInsertEventTimer (Event);
}
}
CoreReleaseLock (&mEfiTimerLock);
}
将每个时间到了的事件,触发,即跑起来。