目标是:在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
完整的代码下载
.inf文件可以发一下不,我编译过程中老出现问题
我记得这个代码没有修改 INF 文件,使用原来的即可。你编译的时候遇到什么问题了?
.c文件会报出很多错误比如说实参和形参的各种错误,还有如果Shell.c不改名字的话会报出Modules have same BaseName and FILE_GUID:这种错误
你的意思是没有修改之前的代码你在编译的时候就会有问题?