terminalconin.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,191 行 · 第 1/2 页
C
1,191 行
return FALSE;
}
TerminalDevice->UnicodeFiFo.Data[Tail] = Input;
TerminalDevice->UnicodeFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
return TRUE;
}
BOOLEAN
UnicodeFiFoRemoveOneKey (
TERMINAL_DEV *TerminalDevice,
UINT16 *Output
)
/*++
Remove one pre-fetched key out of the FIFO buffer.
If FIFO buffer is empty before remove operation,
return FALSE.
--*/
{
UINT8 Head;
Head = TerminalDevice->UnicodeFiFo.Head;
if (IsUnicodeFiFoEmpty (TerminalDevice)) {
//
// FIFO is empty
//
Output = NULL;
return FALSE;
}
*Output = TerminalDevice->UnicodeFiFo.Data[Head];
TerminalDevice->UnicodeFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
return TRUE;
}
BOOLEAN
IsUnicodeFiFoEmpty (
TERMINAL_DEV *TerminalDevice
)
/*++
Clarify whether FIFO buffer is empty.
--*/
{
if (TerminalDevice->UnicodeFiFo.Head == TerminalDevice->UnicodeFiFo.Tail) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
IsUnicodeFiFoFull (
TERMINAL_DEV *TerminalDevice
)
/*++
Clarify whether FIFO buffer is full.
--*/
{
UINT8 Tail;
UINT8 Head;
Tail = TerminalDevice->UnicodeFiFo.Tail;
Head = TerminalDevice->UnicodeFiFo.Head;
if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
return TRUE;
}
return FALSE;
}
UINT8
UnicodeFiFoGetKeyCount (
TERMINAL_DEV *TerminalDevice
)
{
UINT8 Tail;
UINT8 Head;
Tail = TerminalDevice->UnicodeFiFo.Tail;
Head = TerminalDevice->UnicodeFiFo.Head;
if (Tail >= Head) {
return (UINT8) (Tail - Head);
} else {
return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);
}
}
VOID
UnicodeToEfiKeyFlushState (
IN TERMINAL_DEV *TerminalDevice
)
{
EFI_INPUT_KEY Key;
if (TerminalDevice->InputState & INPUT_STATE_ESC) {
Key.ScanCode = SCAN_ESC;
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
}
if (TerminalDevice->InputState & INPUT_STATE_CSI) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = CSI;
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
}
if (TerminalDevice->InputState & INPUT_STATE_LEFTOPENBRACKET) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = LEFTOPENBRACKET;
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
}
if (TerminalDevice->InputState & INPUT_STATE_O) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = 'O';
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
}
if (TerminalDevice->InputState & INPUT_STATE_2) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = '2';
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
}
gBS->SetTimer (
TerminalDevice->TwoSecondTimeOut,
TimerCancel,
0
);
TerminalDevice->InputState = INPUT_STATE_DEFAULT;
}
VOID
UnicodeToEfiKey (
IN TERMINAL_DEV *TerminalDevice
)
/*++
Routine Description:
Converts a stream of Unicode characters from a terminal input device into EFI Keys that
can be read through the Simple Input Protocol. The table below shows the keyboard
input mappings that this function supports. If the ESC sequence listed in one of the
columns is presented, then it is translated into the coorespoding EFI Scan Code. If a
matching sequence is not found, then the raw key strokes are converted into EFI Keys.
2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
converted into EFI Keys.
There is one special input sequence that will force the system to reset.
This is ESC R ESC r ESC R.
Arguments:
TerminaDevice : The terminal device to use to translate raw input into EFI Keys
Returns:
None
Symbols used in table below
===========================
ESC = 0x1B
CSI = 0x9B
DEL = 0x7f
^ = CTRL
+=========+======+===========+==========+==========+
| | EFI | EFI 1.10 | | |
| | Scan | | VT100+ | |
| KEY | Code | PC ANSI | VTUTF8 | VT100 |
+=========+======+===========+==========+==========+
| NULL | 0x00 | | | |
| UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
| DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
| RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
| LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
| HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
| END | 0x06 | ESC [ F | ESC k | ESC [ K |
| INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
| | | ESC [ L | | ESC [ L |
| DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
| PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
| | | | | ESC [ ? |
| PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
| | | | | ESC [ / |
| F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
| F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
| F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
| F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
| F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
| F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
| F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
| F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
| F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
| F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
| Escape | 0x17 | ESC | ESC | ESC |
+=========+======+===========+==========+=========+
Special Mappings
================
ESC R ESC r ESC R = Reset System
--*/
{
EFI_STATUS Status;
EFI_STATUS TimerStatus;
UINT16 UnicodeChar;
EFI_INPUT_KEY Key;
BOOLEAN SetDefaultResetState;
TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
if (!EFI_ERROR (TimerStatus)) {
UnicodeToEfiKeyFlushState (TerminalDevice);
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
}
while (!IsUnicodeFiFoEmpty(TerminalDevice)) {
if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
//
// Check to see if the 2 second timer has expired
//
TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
if (!EFI_ERROR (TimerStatus)) {
UnicodeToEfiKeyFlushState (TerminalDevice);
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
}
}
//
// Fetch one Unicode character from the Unicode FIFO
//
UnicodeFiFoRemoveOneKey (TerminalDevice,&UnicodeChar);
SetDefaultResetState = TRUE;
switch (TerminalDevice->InputState) {
case INPUT_STATE_DEFAULT:
break;
case INPUT_STATE_ESC:
if (UnicodeChar == LEFTOPENBRACKET) {
TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
continue;
}
if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100Type) {
TerminalDevice->InputState |= INPUT_STATE_O;
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
continue;
}
Key.ScanCode = SCAN_NULL;
if (TerminalDevice->TerminalType == VT100PlusType ||
TerminalDevice->TerminalType == VTUTF8Type) {
switch (UnicodeChar) {
case '1':
Key.ScanCode = SCAN_F1;
break;
case '2':
Key.ScanCode = SCAN_F2;
break;
case '3':
Key.ScanCode = SCAN_F3;
break;
case '4':
Key.ScanCode = SCAN_F4;
break;
case '5':
Key.ScanCode = SCAN_F5;
break;
case '6':
Key.ScanCode = SCAN_F6;
break;
case '7':
Key.ScanCode = SCAN_F7;
break;
case '8':
Key.ScanCode = SCAN_F8;
break;
case '9':
Key.ScanCode = SCAN_F9;
break;
case '0':
Key.ScanCode = SCAN_F10;
break;
case 'h':
Key.ScanCode = SCAN_HOME;
break;
case 'k':
Key.ScanCode = SCAN_END;
break;
case '+':
Key.ScanCode = SCAN_INSERT;
break;
case '-':
Key.ScanCode = SCAN_DELETE;
break;
case '/':
Key.ScanCode = SCAN_PAGE_DOWN;
break;
case '?':
Key.ScanCode = SCAN_PAGE_UP;
break;
default :
break;
}
}
switch (UnicodeChar) {
case 'R':
if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
TerminalDevice->ResetState = RESET_STATE_ESC_R;
SetDefaultResetState = FALSE;
} else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) {
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
}
Key.ScanCode = SCAN_NULL;
break;
case 'r':
if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r;
SetDefaultResetState = FALSE;
}
Key.ScanCode = SCAN_NULL;
break;
default :
break;
}
if (SetDefaultResetState) {
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
}
if (Key.ScanCode != SCAN_NULL) {
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
TerminalDevice->InputState = INPUT_STATE_DEFAULT;
UnicodeToEfiKeyFlushState (TerminalDevice);
continue;
}
UnicodeToEfiKeyFlushState (TerminalDevice);
break;
case INPUT_STATE_ESC | INPUT_STATE_O:
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
Key.ScanCode = SCAN_NULL;
if (TerminalDevice->TerminalType == VT100Type) {
switch (UnicodeChar) {
case 'P':
Key.ScanCode = SCAN_F1;
break;
case 'Q':
Key.ScanCode = SCAN_F2;
break;
case 'w':
Key.ScanCode = SCAN_F3;
break;
case 'x':
Key.ScanCode = SCAN_F4;
break;
case 't':
Key.ScanCode = SCAN_F5;
break;
case 'u':
Key.ScanCode = SCAN_F6;
break;
case 'q':
Key.ScanCode = SCAN_F7;
break;
case 'r':
Key.ScanCode = SCAN_F8;
break;
case 'p':
Key.ScanCode = SCAN_F9;
break;
case 'M':
Key.ScanCode = SCAN_F10;
break;
default :
break;
}
}
if (Key.ScanCode != SCAN_NULL) {
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
TerminalDevice->InputState = INPUT_STATE_DEFAULT;
UnicodeToEfiKeyFlushState (TerminalDevice);
continue;
}
UnicodeToEfiKeyFlushState (TerminalDevice);
break;
case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
Key.ScanCode = SCAN_NULL;
if (TerminalDevice->TerminalType == PcAnsiType ||
TerminalDevice->TerminalType == VT100Type ||
TerminalDevice->TerminalType == VT100PlusType ||
TerminalDevice->TerminalType == VTUTF8Type) {
switch (UnicodeChar) {
case 'A':
Key.ScanCode = SCAN_UP;
break;
case 'B':
Key.ScanCode = SCAN_DOWN;
break;
case 'C':
Key.ScanCode = SCAN_RIGHT;
break;
case 'D':
Key.ScanCode = SCAN_LEFT;
break;
case 'H':
if (TerminalDevice->TerminalType == PcAnsiType ||
TerminalDevice->TerminalType == VT100Type) {
Key.ScanCode = SCAN_HOME;
}
break;
case 'F':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_END;
}
break;
case 'K':
if (TerminalDevice->TerminalType == VT100Type) {
Key.ScanCode = SCAN_END;
}
break;
case 'L':
case '@':
if (TerminalDevice->TerminalType == PcAnsiType ||
TerminalDevice->TerminalType == VT100Type) {
Key.ScanCode = SCAN_INSERT;
}
break;
case 'X':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_DELETE;
}
break;
case 'P':
if (TerminalDevice->TerminalType == VT100Type) {
Key.ScanCode = SCAN_DELETE;
} else if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F4;
}
break;
case 'I':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_PAGE_UP;
}
break;
case 'V':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F10;
}
case '?':
if (TerminalDevice->TerminalType == VT100Type) {
Key.ScanCode = SCAN_PAGE_UP;
}
break;
case 'G':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_PAGE_DOWN;
}
break;
case 'U':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F9;
}
case '/':
if (TerminalDevice->TerminalType == VT100Type) {
Key.ScanCode = SCAN_PAGE_DOWN;
}
break;
case 'M':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F1;
}
break;
case 'N':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F2;
}
break;
case 'O':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F3;
}
break;
case 'Q':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F5;
}
break;
case 'R':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F6;
}
break;
case 'S':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F7;
}
break;
case 'T':
if (TerminalDevice->TerminalType == PcAnsiType) {
Key.ScanCode = SCAN_F8;
}
break;
default :
break;
}
}
if (Key.ScanCode != SCAN_NULL) {
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
TerminalDevice->InputState = INPUT_STATE_DEFAULT;
UnicodeToEfiKeyFlushState (TerminalDevice);
continue;
}
UnicodeToEfiKeyFlushState (TerminalDevice);
break;
default:
//
// Invalid state. This should never happen.
//
ASSERT (FALSE);
UnicodeToEfiKeyFlushState (TerminalDevice);
break;
}
if (UnicodeChar == ESC) {
TerminalDevice->InputState = INPUT_STATE_ESC;
}
if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
Status = gBS->SetTimer(
TerminalDevice->TwoSecondTimeOut,
TimerRelative,
(UINT64)20000000
);
continue;
}
if (SetDefaultResetState) {
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
}
if (UnicodeChar == DEL) {
Key.ScanCode = SCAN_DELETE;
Key.UnicodeChar = 0;
} else {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = UnicodeChar;
}
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?