目标是:在Shell的右上角实现一个时间显示,类似DOS下的那种内存驻留程序,不影响其他程序的运行一直显示时间。
方法:首先想到的最简单方法是修改Shell.bin的代码,在开始的地方加入一个定时器,触发之后,首先保存当前光标位置,然后移动光标到右上角,自动更新显示时间,最后再将光标移回原位置。
需要修改的文件是 \ShellPkg\Application\Shell 下面的 Shell.C
定时器触发之后动作的代码如下:
//LabZDebug_Start
/**
The callback function for the timer event used to get map.
@param[in] Event The event this function is registered to.
@param[in] Context The context registered to the event.
**/
VOID
EFIAPI
Timeout (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_TIME ET;
UINTN x;
UINTN y;
//Get cursor postion
x = gST->ConOut->Mode->CursorColumn;
y = gST->ConOut->Mode->CursorRow;
//Move cursor to Up-Left
gST -> ConOut -> SetCursorPosition(gST -> ConOut,70,0);
//Output current time
gRT->GetTime(&ET, NULL);
Print(L"%2d:%2d:%2d",ET.Hour,ET.Minute,ET.Second);
//Move cursor back
gST -> ConOut -> SetCursorPosition(gST -> ConOut,x,y);
return ;
}
//LabZDebug_End
设置定时器的代码如下
//LabZDebug_Start
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL | EVT_TIMER,
TPL_CALLBACK,
Timeout,
NULL,
&TimerOne
);
if (EFI_ERROR (Status)) {
Print(L"Create Event Error! \r\n");
}
else {
Status = gBS->SetTimer (
TimerOne,
TimerPeriodic,
MultU64x32 (1000, 1)
);
if (EFI_ERROR (Status)) {
Print(L"Set Timer Error! \r\n");
}
}
//LabZDebug_End
最后还要销毁定时器,否则会发生 exit 到 setup 之后崩溃的情况
FreeResources: //LabZDebug_Start gBS->SetTimer (TimerOne, TimerCancel, 0); gBS->CloseEvent (TimerOne); //LabZDebug_End
之后需要重新编译出来 Shell.efi 替换原先的文件。运行结果如下
工作的视频:
http://www.tudou.com/programs/view/DcPCkOrO2lQ/?resourceId=414535982_06_02_99
完整的代码下载






















