嗨我是k66,前一篇我們實作顯示系統時間,在那之前前五篇我們實作Logo,本篇要來實作按鍵功能—按ESC退出(詳細欲實現功能請參考本系列文Day11)。
實作按鍵功能主要會使用到4個:EFI_EVENT
、gBS->CreateEvent
、gBS->WaitForEvent
、gST->ConIn->ReadKeyStroke
。
放碼上來!程式碼連結
|-edk2space\edk2\ #若非跟著系列文看上來的新手,edk2安裝請查看[Day7](https://ithelp.ithome.com.tw/articles/10317443)
|-OinkBLPkg
|-ESCevent.c #重點
|-OinkBL.inf
|-OinkBLPkg.dsc
OinkBLPkg.dsc
OinkBL.inf
[Sources]
# Time.c
# Time.h
ESCevent.c
ESCevent.c
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h> //gBS用
#include <Library/MemoryAllocationLib.h>
EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
// Initial
EFI_STATUS Status = EFI_SUCCESS;
ImageHandle=NULL;
SystemTable=NULL;
if (EFI_ERROR(Status))
return Status;
// 創建一個按鍵事件
EFI_EVENT KeyEvent;
Status = gBS->CreateEvent(
EVT_TIMER | EVT_NOTIFY_WAIT,
TPL_CALLBACK,
(EFI_EVENT_NOTIFY)NULL,
NULL,
&KeyEvent
);
if (EFI_ERROR(Status)) {
Print(L"Cannot create a key Event: %r\n", Status);
return Status;
}
// 設置定時器,以便在按下ESC鍵後定期檢查
Status = gBS->SetTimer(
KeyEvent,
TimerRelative,
10000000 // 1000萬微秒(1秒)
);
if (EFI_ERROR(Status)) {
Print(L"Cannot set timer: %r\n", Status);
return Status;
}
// 迴圈,等待ESC鍵按下
Print(L"按下ESC鍵以停止程式...\n");
while(1){
UINTN Index;
EFI_INPUT_KEY Key;
Status = gBS->WaitForEvent(1, &KeyEvent, &Index);
if (!EFI_ERROR(Status)) {
Status = gST->ConIn->ReadKeyStroke(gST->ConIn, &Key);
if (!EFI_ERROR(Status) && Key.ScanCode == SCAN_ESC)
break; // 等ESC鍵被按下,退出迴圈
}
}
// 釋放並退出
gBS->CloseEvent(KeyEvent);
return EFI_SUCCESS;
}
今天是系列文中第一次介紹創建按鍵事件,利用4個:EFI_EVENT
、gBS->CreateEvent
、gBS->WaitForEvent
、gST->ConIn->ReadKeyStroke
,後續我們還會繼續用到。我們明天見!