X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=IntelFrameworkModulePkg%2FCsm%2FBiosThunk%2FKeyboardDxe%2FBiosKeyboard.c;h=ec525891dc7a5659af89d1151a008ee1cc84fd4f;hp=06ef9d3345648e11824cbd2fc16ee18276b0f183;hb=621d1f45adf4b9ba73adfefc41e4b17b89623aad;hpb=bcecde140a561c64e297225904afebebd62336ce
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
index 06ef9d3345..ec525891dc 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
@@ -1,7 +1,7 @@
/** @file
ConsoleOut Routines that speak VGA.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -272,6 +272,8 @@ BiosKeyboardDriverBindingStart (
BiosKeyboardPrivate->Queue.Front = 0;
BiosKeyboardPrivate->Queue.Rear = 0;
+ BiosKeyboardPrivate->QueueForNotify.Front = 0;
+ BiosKeyboardPrivate->QueueForNotify.Rear = 0;
BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx;
BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx;
BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState;
@@ -279,19 +281,12 @@ BiosKeyboardDriverBindingStart (
BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify;
InitializeListHead (&BiosKeyboardPrivate->NotifyList);
- Status = gBS->HandleProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &BiosKeyboardPrivate->DevicePath
- );
-
//
// Report that the keyboard is being enabled
//
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ REPORT_STATUS_CODE (
EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
- BiosKeyboardPrivate->DevicePath
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE
);
//
@@ -346,14 +341,26 @@ BiosKeyboardDriverBindingStart (
StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
goto Done;
}
-
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ KeyNotifyProcessHandler,
+ BiosKeyboardPrivate,
+ &BiosKeyboardPrivate->KeyNotifyProcessEvent
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+ goto Done;
+ }
+
//
// Report a Progress Code for an attempt to detect the precense of the keyboard device in the system
//
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ REPORT_STATUS_CODE (
EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
- BiosKeyboardPrivate->DevicePath
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT
);
//
@@ -361,10 +368,10 @@ BiosKeyboardDriverBindingStart (
//
Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset (
&BiosKeyboardPrivate->SimpleTextInputEx,
- FALSE
+ FeaturePcdGet (PcdPs2KbdExtendedVerification)
);
-
if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));
StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
goto Done;
}
@@ -411,7 +418,7 @@ BiosKeyboardDriverBindingStart (
// Check bit 6 of Feature Byte 2.
// If it is set, then Int 16 Func 09 is supported
//
- if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {
+ if (*(UINT8 *) (((UINTN) Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {
//
// Get Keyboard Functionality
//
@@ -436,6 +443,7 @@ BiosKeyboardDriverBindingStart (
}
}
}
+ DEBUG ((EFI_D_INFO, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN)BiosKeyboardPrivate->ExtendedKeyboard));
//
// Install protocol interfaces for the keyboard device.
//
@@ -453,10 +461,9 @@ Done:
//
// Report an Error Code for failing to start the keyboard device
//
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ REPORT_STATUS_CODE (
EFI_ERROR_CODE | EFI_ERROR_MINOR,
- StatusCode,
- BiosKeyboardPrivate->DevicePath
+ StatusCode
);
}
@@ -470,6 +477,11 @@ Done:
if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {
gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx);
}
+
+ if (BiosKeyboardPrivate->KeyNotifyProcessEvent != NULL) {
+ gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);
+ }
+
BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);
if (BiosKeyboardPrivate->TimerEvent != NULL) {
@@ -574,6 +586,7 @@ BiosKeyboardDriverBindingStop (
gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);
gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);
gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx);
+ gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);
BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);
FreePool (BiosKeyboardPrivate);
@@ -942,7 +955,7 @@ KeyboardReadKeyStrokeWorker (
}
//
- // Use TimerEvent callback funciton to check whether there's any key pressed
+ // Use TimerEvent callback function to check whether there's any key pressed
//
//
@@ -986,7 +999,7 @@ KeyboardReadKeyStrokeWorker (
@param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.
@retval EFI_SUCCESS The command byte is written successfully.
- @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard.
+ @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard.
**/
EFI_STATUS
@@ -1010,19 +1023,17 @@ BiosKeyboardReset (
// 1
// Report reset progress code
//
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ REPORT_STATUS_CODE (
EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
- BiosKeyboardPrivate->DevicePath
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET
);
//
// Report a Progress Code for clearing the keyboard buffer
//
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ REPORT_STATUS_CODE (
EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
- BiosKeyboardPrivate->DevicePath
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER
);
//
@@ -1047,96 +1058,96 @@ BiosKeyboardReset (
// if not skip step 4&5 and jump to step 6 to selftest KBC and report this
// else go step 4
//
- if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {
- //
- // 4
- // CheckMouseStatus to decide enable it later or not
- //
- //
- // Read the command byte of KBC
- //
- Status = KeyboardCommand (
- BiosKeyboardPrivate,
- KBC_CMDREG_VIA64_CMDBYTE_R
- );
-
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
- }
-
- Status = KeyboardRead (
- BiosKeyboardPrivate,
- &CommandByte
- );
-
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
- }
- //
- // Check mouse enabled or not before
- //
- if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {
- MouseEnable = FALSE;
+ if (!PcdGetBool (PcdFastPS2Detection)) {
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {
+ //
+ // 4
+ // CheckMouseStatus to decide enable it later or not
+ //
+ //
+ // Read the command byte of KBC
+ //
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_CMDBYTE_R
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardRead (
+ BiosKeyboardPrivate,
+ &CommandByte
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // Check mouse enabled or not before
+ //
+ if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {
+ MouseEnable = FALSE;
+ } else {
+ MouseEnable = TRUE;
+ }
+ //
+ // 5
+ // disable mouse (via KBC) and Keyborad device
+ //
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_AUX_DISABLE
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_KB_DISABLE
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
} else {
- MouseEnable = TRUE;
- }
- //
- // 5
- // disable mouse (via KBC) and Keyborad device
- //
- Status = KeyboardCommand (
- BiosKeyboardPrivate,
- KBC_CMDREG_VIA64_AUX_DISABLE
- );
-
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
- }
-
- Status = KeyboardCommand (
- BiosKeyboardPrivate,
- KBC_CMDREG_VIA64_KB_DISABLE
- );
-
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
- }
-
- } else {
- //
- // 6
- // KBC Self Test
- //
- //
- // Report a Progress Code for performing a self test on the keyboard controller
- //
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
- BiosKeyboardPrivate->DevicePath
- );
-
- Status = KeyboardCommand (
- BiosKeyboardPrivate,
- KBC_CMDREG_VIA64_KBC_SLFTEST
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
- }
-
- Status = KeyboardWaitForValue (
- BiosKeyboardPrivate,
- KBC_CMDECHO_KBCSLFTEST_OK,
- KEYBOARD_WAITFORVALUE_TIMEOUT
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
+ //
+ // 6
+ // KBC Self Test
+ //
+ //
+ // Report a Progress Code for performing a self test on the keyboard controller
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST
+ );
+
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_KBC_SLFTEST
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_KBCSLFTEST_OK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
}
}
//
@@ -1186,8 +1197,8 @@ BiosKeyboardReset (
);
//
- // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
- // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped.
+ // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
+ // so we only do the real resetting for keyboard when user asks, and normally during booting an OS, it's skipped.
// Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,
// Real reset will not do.
//
@@ -1332,14 +1343,16 @@ BiosKeyboardReset (
// Done for validating keyboard. Enable keyboard (via KBC)
// and recover the command byte to proper value
//
- Status = KeyboardCommand (
- BiosKeyboardPrivate,
- KBC_CMDREG_VIA64_KB_ENABLE
- );
-
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
+ if (!PcdGetBool (PcdFastPS2Detection)) {
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_KB_ENABLE
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
}
//
@@ -1397,6 +1410,17 @@ BiosKeyboardReadKeyStroke (
return Status;
}
+ //
+ // Convert the Ctrl+[a-z] to Ctrl+[1-26]
+ //
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
+ if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);
+ } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);
+ }
+ }
+
CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
return EFI_SUCCESS;
@@ -1428,7 +1452,7 @@ BiosKeyboardWaitForKey (
//
gBS->Stall (1000);
//
- // Use TimerEvent callback funciton to check whether there's any key pressed
+ // Use TimerEvent callback function to check whether there's any key pressed
//
BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));
@@ -1674,25 +1698,38 @@ CheckKeyboardConnect (
// enable keyboard itself and wait for its ack
// If can't receive ack, Keyboard should not be connected.
//
- Status = KeyboardWrite (
- BiosKeyboardPrivate,
- KBC_INPBUF_VIA60_KBEN
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
+ if (!PcdGetBool (PcdFastPS2Detection)) {
+ Status = KeyboardWrite (
+ BiosKeyboardPrivate,
+ KBC_INPBUF_VIA60_KBEN
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n"));
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR
+ );
+ return FALSE;
+ }
- Status = KeyboardWaitForValue (
- BiosKeyboardPrivate,
- KBC_CMDECHO_ACK,
- KEYBOARD_WAITFORVALUE_TIMEOUT
- );
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_ACK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
- if (EFI_ERROR (Status)) {
- return FALSE;
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Timeout!\n"));
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR
+ );
+ return FALSE;
+ }
+ return TRUE;
+ } else {
+ return TRUE;
}
-
- return TRUE;
}
/**
@@ -1763,6 +1800,13 @@ BiosKeyboardTimerHandler (
KeyData.Key.ScanCode = (UINT16) Regs.H.AH;
KeyData.Key.UnicodeChar = (UINT16) Regs.H.AL;
+ DEBUG ((
+ EFI_D_INFO,
+ "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
+ KeyData.Key.ScanCode,
+ KeyData.Key.UnicodeChar
+ ));
+
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
//
@@ -1772,7 +1816,7 @@ BiosKeyboardTimerHandler (
// will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when
// KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit
// in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode
- // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other dirvers
+ // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other drivers
// performance, like USB.
//
// 1. If CTRL or ALT release code is missed, all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In
@@ -1798,8 +1842,44 @@ BiosKeyboardTimerHandler (
//
// Clear the CTRL and ALT BDA flag
//
- KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1
- KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2
+ ACCESS_PAGE0_CODE (
+ KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1
+ KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2
+ );
+
+ DEBUG_CODE (
+ {
+ if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {
+ DEBUG ((EFI_D_INFO, "[KBD]Caps Lock Key is pressed.\n"));
+ }
+ if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {
+ DEBUG ((EFI_D_INFO, "[KBD]Num Lock Key is pressed.\n"));
+ }
+ if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {
+ DEBUG ((EFI_D_INFO, "[KBD]Scroll Lock Key is pressed.\n"));
+ }
+ if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {
+ if ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) {
+ DEBUG ((EFI_D_INFO, "[KBD]Left Alt Key is pressed.\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "[KBD]Right Alt Key is pressed.\n"));
+ }
+ }
+ if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {
+ if ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) {
+ DEBUG ((EFI_D_INFO, "[KBD]Left Ctrl Key is pressed.\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "[KBD]Right Ctrl Key is pressed.\n"));
+ }
+ }
+ if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {
+ DEBUG ((EFI_D_INFO, "[KBD]Left Shift Key is pressed.\n"));
+ }
+ if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {
+ DEBUG ((EFI_D_INFO, "[KBD]Right Shift Key is pressed.\n"));
+ }
+ }
+ );
//
// Record toggle state
@@ -1833,11 +1913,12 @@ BiosKeyboardTimerHandler (
//
// Clear left alt and left ctrl BDA flag
//
- KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);
- *((UINT8 *) (UINTN) 0x418) = KbFlag2;
- KbFlag1 &= ~0x0C;
- *((UINT8 *) (UINTN) 0x417) = KbFlag1;
-
+ ACCESS_PAGE0_CODE (
+ KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);
+ *((UINT8 *) (UINTN) 0x418) = KbFlag2;
+ KbFlag1 &= ~0x0C;
+ *((UINT8 *) (UINTN) 0x417) = KbFlag1;
+ );
//
// Output EFI input key and shift/toggle state
@@ -1864,6 +1945,13 @@ BiosKeyboardTimerHandler (
}
}
+ DEBUG ((
+ EFI_D_INFO,
+ "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
+ KeyData.Key.ScanCode,
+ KeyData.Key.UnicodeChar
+ ));
+
//
// Need not return associated shift state if a class of printable characters that
// are normally adjusted by shift modifiers.
@@ -1872,11 +1960,12 @@ BiosKeyboardTimerHandler (
if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') ||
(KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z')
) {
+ DEBUG ((EFI_D_INFO, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n"));
KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
}
//
- // Invoke notification functions if exist
+ // Signal KeyNotify process event if this key pressed matches any key registered.
//
for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
CurrentNotify = CR (
@@ -1885,21 +1974,17 @@ BiosKeyboardTimerHandler (
NotifyEntry,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
- if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
- CurrentNotify->KeyNotificationFn (&KeyData);
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+ //
+ // The key notification function needs to run at TPL_CALLBACK
+ // while current TPL is TPL_NOTIFY. It will be invoked in
+ // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
+ //
+ Enqueue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);
+ gBS->SignalEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);
}
}
- //
- // Convert the Ctrl+[a-z] to Ctrl+[1-26]
- //
- if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
- if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
- KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + 1);
- } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
- KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + 1);
- }
- }
Enqueue (&BiosKeyboardPrivate->Queue, &KeyData);
//
// Leave critical section and return
@@ -1909,6 +1994,55 @@ BiosKeyboardTimerHandler (
return ;
}
+/**
+ Process key notify.
+
+ @param Event Indicates the event that invoke this function.
+ @param Context Indicates the calling context.
+**/
+VOID
+EFIAPI
+KeyNotifyProcessHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_KEY_DATA KeyData;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NotifyList;
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+ EFI_TPL OldTpl;
+
+ BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) Context;
+
+ //
+ // Invoke notification functions.
+ //
+ NotifyList = &BiosKeyboardPrivate->NotifyList;
+ while (TRUE) {
+ //
+ // Enter critical section
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ Status = Dequeue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);
+ //
+ // Leave critical section
+ //
+ gBS->RestoreTPL (OldTpl);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
+ CurrentNotify = CR (Link, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+ CurrentNotify->KeyNotificationFn (&KeyData);
+ }
+ }
+ }
+}
+
/**
Free keyboard notify list.
@@ -2109,7 +2243,12 @@ BiosKeyboardSetState (
return EFI_INVALID_PARAMETER;
}
- if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
+ //
+ // Thunk keyboard driver doesn't support partial keystroke.
+ //
+ if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID ||
+ (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED
+ ) {
return EFI_UNSUPPORTED;
}
@@ -2142,15 +2281,18 @@ BiosKeyboardSetState (
Status = KeyboardWrite (BiosKeyboardPrivate, 0xed);
if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
}
Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);
if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
}
Status = KeyboardWrite (BiosKeyboardPrivate, Command);
if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
}
//
// Call Legacy BIOS Protocol to set whatever is necessary
@@ -2159,6 +2301,7 @@ BiosKeyboardSetState (
Status = EFI_SUCCESS;
+Exit:
//
// Leave critical section and return
//
@@ -2173,24 +2316,27 @@ BiosKeyboardSetState (
@param This Protocol instance pointer.
@param KeyData A pointer to a buffer that is filled in with the keystroke
- information data for the key that was pressed.
+ information data for the key that was pressed. If KeyData.Key,
+ KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState
+ are 0, then any incomplete keystroke will trigger a notification of
+ the KeyNotificationFunction.
@param KeyNotificationFunction Points to the function to be called when the key
- sequence is typed specified by KeyData.
- @param NotifyHandle Points to the unique handle assigned to the registered notification.
+ sequence is typed specified by KeyData. This notification function
+ should be called at <=TPL_CALLBACK.
+ @param NotifyHandle Points to the unique handle assigned to the registered notification.
-
@retval EFI_SUCCESS The notification function was registered successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
@retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
-
-**/
+
+**/
EFI_STATUS
EFIAPI
BiosKeyboardRegisterKeyNotify (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN EFI_KEY_DATA *KeyData,
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
- OUT EFI_HANDLE *NotifyHandle
+ OUT VOID **NotifyHandle
)
{
EFI_STATUS Status;
@@ -2223,7 +2369,7 @@ BiosKeyboardRegisterKeyNotify (
);
if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
- *NotifyHandle = CurrentNotify->NotifyHandle;
+ *NotifyHandle = CurrentNotify;
Status = EFI_SUCCESS;
goto Exit;
}
@@ -2242,11 +2388,10 @@ BiosKeyboardRegisterKeyNotify (
NewNotify->Signature = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
NewNotify->KeyNotificationFn = KeyNotificationFunction;
- NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;
CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);
- *NotifyHandle = NewNotify->NotifyHandle;
+ *NotifyHandle = NewNotify;
Status = EFI_SUCCESS;
Exit:
@@ -2271,7 +2416,7 @@ EFI_STATUS
EFIAPI
BiosKeyboardUnregisterKeyNotify (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- IN EFI_HANDLE NotificationHandle
+ IN VOID *NotificationHandle
)
{
EFI_STATUS Status;
@@ -2296,7 +2441,7 @@ BiosKeyboardUnregisterKeyNotify (
//
// Enter critical section
//
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
CurrentNotify = CR (
@@ -2305,7 +2450,7 @@ BiosKeyboardUnregisterKeyNotify (
NotifyEntry,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
- if (CurrentNotify->NotifyHandle == NotificationHandle) {
+ if (CurrentNotify == NotificationHandle) {
//
// Remove the notification function from NotifyList and free resources
//