]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
IntelFrameworkModulePkg Ps2KbDxe: Execute key notify func at TPL_CALLBACK
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / BiosThunk / KeyboardDxe / BiosKeyboard.c
index 06ef9d3345648e11824cbd2fc16ee18276b0f183..8dcb13177881cd51ba263df0a834376fb416f6a6 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   ConsoleOut Routines that speak VGA.\r
 \r
 /** @file\r
   ConsoleOut Routines that speak VGA.\r
 \r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
@@ -279,19 +279,12 @@ BiosKeyboardDriverBindingStart (
   BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify;    \r
   InitializeListHead (&BiosKeyboardPrivate->NotifyList);\r
 \r
   BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify;    \r
   InitializeListHead (&BiosKeyboardPrivate->NotifyList);\r
 \r
-  Status = gBS->HandleProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &BiosKeyboardPrivate->DevicePath\r
-                  );\r
-\r
   //\r
   // Report that the keyboard is being enabled\r
   //\r
   //\r
   // Report that the keyboard is being enabled\r
   //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+  REPORT_STATUS_CODE (\r
     EFI_PROGRESS_CODE,\r
     EFI_PROGRESS_CODE,\r
-    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,\r
-    BiosKeyboardPrivate->DevicePath\r
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE\r
     );\r
 \r
   //\r
     );\r
 \r
   //\r
@@ -350,10 +343,9 @@ BiosKeyboardDriverBindingStart (
   //\r
   // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system\r
   //\r
   //\r
   // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system\r
   //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+  REPORT_STATUS_CODE (\r
     EFI_PROGRESS_CODE,\r
     EFI_PROGRESS_CODE,\r
-    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,\r
-    BiosKeyboardPrivate->DevicePath\r
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT\r
     );\r
 \r
   //\r
     );\r
 \r
   //\r
@@ -361,10 +353,10 @@ BiosKeyboardDriverBindingStart (
   //\r
   Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset (\r
                                                     &BiosKeyboardPrivate->SimpleTextInputEx,\r
   //\r
   Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset (\r
                                                     &BiosKeyboardPrivate->SimpleTextInputEx,\r
-                                                    FALSE\r
+                                                    FeaturePcdGet (PcdPs2KbdExtendedVerification)\r
                                                     );\r
                                                     );\r
-\r
   if (EFI_ERROR (Status)) {\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));  \r
     StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;\r
     goto Done;\r
   }\r
     StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;\r
     goto Done;\r
   }\r
@@ -436,6 +428,7 @@ BiosKeyboardDriverBindingStart (
       }\r
     }\r
   }\r
       }\r
     }\r
   }\r
+  DEBUG ((EFI_D_INFO, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN)BiosKeyboardPrivate->ExtendedKeyboard));\r
   //\r
   // Install protocol interfaces for the keyboard device.\r
   //\r
   //\r
   // Install protocol interfaces for the keyboard device.\r
   //\r
@@ -453,10 +446,9 @@ Done:
     //\r
     // Report an Error Code for failing to start the keyboard device\r
     //\r
     //\r
     // Report an Error Code for failing to start the keyboard device\r
     //\r
-    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    REPORT_STATUS_CODE (\r
       EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
       EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-      StatusCode,\r
-      BiosKeyboardPrivate->DevicePath\r
+      StatusCode\r
       );\r
   }\r
 \r
       );\r
   }\r
 \r
@@ -942,7 +934,7 @@ KeyboardReadKeyStrokeWorker (
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  // Use TimerEvent callback funciton to check whether there's any key pressed\r
+  // Use TimerEvent callback function to check whether there's any key pressed\r
   //\r
   \r
   //\r
   //\r
   \r
   //\r
@@ -986,7 +978,7 @@ KeyboardReadKeyStrokeWorker (
   @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.\r
 \r
   @retval EFI_SUCCESS           The command byte is written successfully.\r
   @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.\r
 \r
   @retval EFI_SUCCESS           The command byte is written successfully.\r
-  @retval EFI_DEVICE_ERROR      Errors occurred during reseting keyboard.\r
+  @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.\r
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1010,19 +1002,17 @@ BiosKeyboardReset (
   // 1\r
   // Report reset progress code\r
   //\r
   // 1\r
   // Report reset progress code\r
   //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+  REPORT_STATUS_CODE (\r
     EFI_PROGRESS_CODE,\r
     EFI_PROGRESS_CODE,\r
-    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,\r
-    BiosKeyboardPrivate->DevicePath\r
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET\r
     );\r
 \r
   //\r
   // Report a Progress Code for clearing the keyboard buffer\r
   //\r
     );\r
 \r
   //\r
   // Report a Progress Code for clearing the keyboard buffer\r
   //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+  REPORT_STATUS_CODE (\r
     EFI_PROGRESS_CODE,\r
     EFI_PROGRESS_CODE,\r
-    EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,\r
-    BiosKeyboardPrivate->DevicePath\r
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER\r
     );\r
 \r
   //\r
     );\r
 \r
   //\r
@@ -1047,96 +1037,96 @@ BiosKeyboardReset (
   // if not skip step 4&5 and jump to step 6 to selftest KBC and report this\r
   // else   go step 4\r
   //\r
   // if not skip step 4&5 and jump to step 6 to selftest KBC and report this\r
   // else   go step 4\r
   //\r
-  if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {\r
-    //\r
-    // 4\r
-    // CheckMouseStatus to decide enable it later or not\r
-    //\r
-    //\r
-    // Read the command byte of KBC\r
-    //\r
-    Status = KeyboardCommand (\r
-               BiosKeyboardPrivate,\r
-               KBC_CMDREG_VIA64_CMDBYTE_R\r
-               );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      Status    = EFI_DEVICE_ERROR;\r
-      goto Exit;\r
-    }\r
-\r
-    Status = KeyboardRead (\r
-               BiosKeyboardPrivate,\r
-               &CommandByte\r
-               );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      Status    = EFI_DEVICE_ERROR;\r
-      goto Exit;\r
-    }\r
-    //\r
-    // Check mouse enabled or not before\r
-    //\r
-    if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {\r
-      MouseEnable = FALSE;\r
+  if (!PcdGetBool (PcdFastPS2Detection)) {\r
+    if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {\r
+      //\r
+      // 4\r
+      // CheckMouseStatus to decide enable it later or not\r
+      //\r
+      //\r
+      // Read the command byte of KBC\r
+      //\r
+      Status = KeyboardCommand (\r
+                 BiosKeyboardPrivate,\r
+                 KBC_CMDREG_VIA64_CMDBYTE_R\r
+                 );\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        Status    = EFI_DEVICE_ERROR;\r
+        goto Exit;\r
+      }\r
+      \r
+      Status = KeyboardRead (\r
+                 BiosKeyboardPrivate,\r
+                 &CommandByte\r
+                 );\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        Status    = EFI_DEVICE_ERROR;\r
+        goto Exit;\r
+      }\r
+      //\r
+      // Check mouse enabled or not before\r
+      //\r
+      if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {\r
+        MouseEnable = FALSE;\r
+      } else {\r
+        MouseEnable = TRUE;\r
+      }\r
+      //\r
+      // 5\r
+      // disable mouse (via KBC) and Keyborad device\r
+      //\r
+      Status = KeyboardCommand (\r
+                 BiosKeyboardPrivate,\r
+                 KBC_CMDREG_VIA64_AUX_DISABLE\r
+                 );\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        Status    = EFI_DEVICE_ERROR;\r
+        goto Exit;\r
+      }\r
+      \r
+      Status = KeyboardCommand (\r
+                 BiosKeyboardPrivate,\r
+                 KBC_CMDREG_VIA64_KB_DISABLE\r
+                 );\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        Status    = EFI_DEVICE_ERROR;\r
+        goto Exit;\r
+      }\r
     } else {\r
     } else {\r
-      MouseEnable = TRUE;\r
-    }\r
-    //\r
-    // 5\r
-    // disable mouse (via KBC) and Keyborad device\r
-    //\r
-    Status = KeyboardCommand (\r
-               BiosKeyboardPrivate,\r
-               KBC_CMDREG_VIA64_AUX_DISABLE\r
-               );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      Status    = EFI_DEVICE_ERROR;\r
-      goto Exit;\r
-    }\r
-\r
-    Status = KeyboardCommand (\r
-               BiosKeyboardPrivate,\r
-               KBC_CMDREG_VIA64_KB_DISABLE\r
-               );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      Status    = EFI_DEVICE_ERROR;\r
-      goto Exit;\r
-    }\r
-\r
-  } else {\r
-    //\r
-    // 6\r
-    // KBC Self Test\r
-    //\r
-    //\r
-    // Report a Progress Code for performing a self test on the keyboard controller\r
-    //\r
-    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-      EFI_PROGRESS_CODE,\r
-      EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,\r
-      BiosKeyboardPrivate->DevicePath\r
-      );\r
-\r
-    Status = KeyboardCommand (\r
-               BiosKeyboardPrivate,\r
-               KBC_CMDREG_VIA64_KBC_SLFTEST\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      Status    = EFI_DEVICE_ERROR;\r
-      goto Exit;\r
-    }\r
-\r
-    Status = KeyboardWaitForValue (\r
-               BiosKeyboardPrivate,\r
-               KBC_CMDECHO_KBCSLFTEST_OK,\r
-               KEYBOARD_WAITFORVALUE_TIMEOUT\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      Status    = EFI_DEVICE_ERROR;\r
-      goto Exit;\r
+      //\r
+      // 6\r
+      // KBC Self Test\r
+      //\r
+      //\r
+      // Report a Progress Code for performing a self test on the keyboard controller\r
+      //    \r
+      REPORT_STATUS_CODE (\r
+        EFI_PROGRESS_CODE,\r
+        EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST\r
+        );\r
+      \r
+      Status = KeyboardCommand (\r
+                 BiosKeyboardPrivate,\r
+                 KBC_CMDREG_VIA64_KBC_SLFTEST\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        Status    = EFI_DEVICE_ERROR;\r
+        goto Exit;\r
+      }\r
+      \r
+      Status = KeyboardWaitForValue (\r
+                 BiosKeyboardPrivate,\r
+                 KBC_CMDECHO_KBCSLFTEST_OK,\r
+                 KEYBOARD_WAITFORVALUE_TIMEOUT\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        Status    = EFI_DEVICE_ERROR;\r
+        goto Exit;\r
+      }\r
     }\r
   }\r
   //\r
     }\r
   }\r
   //\r
@@ -1186,8 +1176,8 @@ BiosKeyboardReset (
              );\r
 \r
   //\r
              );\r
 \r
   //\r
-  // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
-  // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped.\r
+  // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
+  // so we only do the real resetting for keyboard when user asks, and normally during booting an OS, it's skipped.\r
   // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,\r
   // Real reset will not do.\r
   //\r
   // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,\r
   // Real reset will not do.\r
   //\r
@@ -1332,14 +1322,16 @@ BiosKeyboardReset (
   // Done for validating keyboard. Enable keyboard (via KBC)\r
   // and recover the command byte to proper value\r
   //\r
   // Done for validating keyboard. Enable keyboard (via KBC)\r
   // and recover the command byte to proper value\r
   //\r
-  Status = KeyboardCommand (\r
-             BiosKeyboardPrivate,\r
-             KBC_CMDREG_VIA64_KB_ENABLE\r
-             );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    Status    = EFI_DEVICE_ERROR;\r
-    goto Exit;\r
+  if (!PcdGetBool (PcdFastPS2Detection)) {\r
+    Status = KeyboardCommand (\r
+               BiosKeyboardPrivate,\r
+               KBC_CMDREG_VIA64_KB_ENABLE\r
+               );\r
+    \r
+    if (EFI_ERROR (Status)) {\r
+      Status    = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -1397,6 +1389,17 @@ BiosKeyboardReadKeyStroke (
     return Status;\r
   }\r
 \r
     return Status;\r
   }\r
 \r
+  //\r
+  // Convert the Ctrl+[a-z] to Ctrl+[1-26]\r
+  //\r
+  if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+    if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
+      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
+    } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
+      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
+    }\r
+  }\r
+\r
   CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));  \r
 \r
   return EFI_SUCCESS;\r
   CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));  \r
 \r
   return EFI_SUCCESS;\r
@@ -1428,7 +1431,7 @@ BiosKeyboardWaitForKey (
   //\r
   gBS->Stall (1000);\r
   //\r
   //\r
   gBS->Stall (1000);\r
   //\r
-  // Use TimerEvent callback funciton to check whether there's any key pressed\r
+  // Use TimerEvent callback function to check whether there's any key pressed\r
   //\r
   BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));\r
 \r
   //\r
   BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));\r
 \r
@@ -1674,25 +1677,38 @@ CheckKeyboardConnect (
   // enable keyboard itself and wait for its ack\r
   // If can't receive ack, Keyboard should not be connected.\r
   //\r
   // enable keyboard itself and wait for its ack\r
   // If can't receive ack, Keyboard should not be connected.\r
   //\r
-  Status = KeyboardWrite (\r
-             BiosKeyboardPrivate,\r
-             KBC_INPBUF_VIA60_KBEN\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
+  if (!PcdGetBool (PcdFastPS2Detection)) {\r
+    Status = KeyboardWrite (\r
+               BiosKeyboardPrivate,\r
+               KBC_INPBUF_VIA60_KBEN\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n"));\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR\r
+        );\r
+      return FALSE;\r
+    }\r
 \r
 \r
-  Status = KeyboardWaitForValue (\r
-             BiosKeyboardPrivate,\r
-             KBC_CMDECHO_ACK,\r
-             KEYBOARD_WAITFORVALUE_TIMEOUT\r
-             );\r
+    Status = KeyboardWaitForValue (\r
+               BiosKeyboardPrivate,\r
+               KBC_CMDECHO_ACK,\r
+               KEYBOARD_WAITFORVALUE_TIMEOUT\r
+               );\r
 \r
 \r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Timeout!\n"));\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR\r
+        );\r
+      return FALSE;\r
+    }\r
+    return TRUE;\r
+  } else {\r
+    return TRUE;\r
   }\r
   }\r
-\r
-  return TRUE;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -1763,6 +1779,13 @@ BiosKeyboardTimerHandler (
 \r
   KeyData.Key.ScanCode            = (UINT16) Regs.H.AH;\r
   KeyData.Key.UnicodeChar         = (UINT16) Regs.H.AL;\r
 \r
   KeyData.Key.ScanCode            = (UINT16) Regs.H.AH;\r
   KeyData.Key.UnicodeChar         = (UINT16) Regs.H.AL;\r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",\r
+    KeyData.Key.ScanCode,\r
+    KeyData.Key.UnicodeChar\r
+    ));\r
+  \r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
   KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
   //\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
   KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
   //\r
@@ -1772,7 +1795,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 \r
   // 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 \r
   // 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 \r
   // 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 \r
   // 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 \r
   // 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 \r
-  // 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 \r
+  // 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\r
   // performance, like USB.\r
   //\r
   // 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 \r
   // performance, like USB.\r
   //\r
   // 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 \r
@@ -1801,6 +1824,40 @@ BiosKeyboardTimerHandler (
   KbFlag1 = *((UINT8 *) (UINTN) 0x417);  // read the STATUS FLAGS 1\r
   KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2\r
 \r
   KbFlag1 = *((UINT8 *) (UINTN) 0x417);  // read the STATUS FLAGS 1\r
   KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2\r
 \r
+  DEBUG_CODE (\r
+    {\r
+      if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {\r
+        DEBUG ((EFI_D_INFO, "[KBD]Caps Lock Key is pressed.\n"));\r
+      }\r
+      if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {\r
+        DEBUG ((EFI_D_INFO, "[KBD]Num Lock Key is pressed.\n"));\r
+      }\r
+      if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {\r
+        DEBUG ((EFI_D_INFO, "[KBD]Scroll Lock Key is pressed.\n"));\r
+      } \r
+      if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {\r
+        if ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) {\r
+          DEBUG ((EFI_D_INFO, "[KBD]Left Alt Key is pressed.\n"));\r
+        } else {\r
+          DEBUG ((EFI_D_INFO, "[KBD]Right Alt Key is pressed.\n"));\r
+        }\r
+      }  \r
+      if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {\r
+        if ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) {\r
+          DEBUG ((EFI_D_INFO, "[KBD]Left Ctrl Key is pressed.\n"));\r
+        } else {\r
+          DEBUG ((EFI_D_INFO, "[KBD]Right Ctrl Key is pressed.\n"));\r
+        }\r
+      }  \r
+      if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {\r
+        DEBUG ((EFI_D_INFO, "[KBD]Left Shift Key is pressed.\n"));\r
+      }\r
+      if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {\r
+        DEBUG ((EFI_D_INFO, "[KBD]Right Shift Key is pressed.\n"));\r
+      }\r
+    }\r
+  );\r
+\r
   //\r
   // Record toggle state\r
   //\r
   //\r
   // Record toggle state\r
   //\r
@@ -1864,6 +1921,13 @@ BiosKeyboardTimerHandler (
     }\r
   }\r
 \r
     }\r
   }\r
 \r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",\r
+    KeyData.Key.ScanCode,\r
+    KeyData.Key.UnicodeChar\r
+    ));\r
+\r
   //\r
   // Need not return associated shift state if a class of printable characters that\r
   // are normally adjusted by shift modifiers.\r
   //\r
   // Need not return associated shift state if a class of printable characters that\r
   // are normally adjusted by shift modifiers.\r
@@ -1872,6 +1936,7 @@ BiosKeyboardTimerHandler (
   if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') ||\r
       (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z')\r
      ) {\r
   if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') ||\r
       (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z')\r
      ) {\r
+    DEBUG ((EFI_D_INFO, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n"));\r
     KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r
   }\r
 \r
     KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r
   }\r
 \r
@@ -1890,16 +1955,6 @@ BiosKeyboardTimerHandler (
     }\r
   }\r
 \r
     }\r
   }\r
 \r
-  //\r
-  // Convert the Ctrl+[a-z] to Ctrl+[1-26]\r
-  //\r
-  if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
-    if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
-      KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
-    } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
-      KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
-    }\r
-  }\r
   Enqueue (&BiosKeyboardPrivate->Queue, &KeyData);\r
   //\r
   // Leave critical section and return\r
   Enqueue (&BiosKeyboardPrivate->Queue, &KeyData);\r
   //\r
   // Leave critical section and return\r
@@ -2109,7 +2164,12 @@ BiosKeyboardSetState (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
+  //\r
+  // Thunk keyboard driver doesn't support partial keystroke.\r
+  //\r
+  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID ||\r
+      (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED\r
+      ) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -2142,15 +2202,18 @@ BiosKeyboardSetState (
 \r
   Status = KeyboardWrite (BiosKeyboardPrivate, 0xed);\r
   if (EFI_ERROR (Status)) {\r
 \r
   Status = KeyboardWrite (BiosKeyboardPrivate, 0xed);\r
   if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Exit;\r
   }  \r
   Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
   }  \r
   Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Exit;\r
   }\r
   Status = KeyboardWrite (BiosKeyboardPrivate, Command);\r
   if (EFI_ERROR (Status)) {\r
   }\r
   Status = KeyboardWrite (BiosKeyboardPrivate, Command);\r
   if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Exit;\r
   }  \r
   //\r
   // Call Legacy BIOS Protocol to set whatever is necessary\r
   }  \r
   //\r
   // Call Legacy BIOS Protocol to set whatever is necessary\r
@@ -2159,6 +2222,7 @@ BiosKeyboardSetState (
 \r
   Status = EFI_SUCCESS;\r
 \r
 \r
   Status = EFI_SUCCESS;\r
 \r
+Exit:\r
   //\r
   // Leave critical section and return\r
   //\r
   //\r
   // Leave critical section and return\r
   //\r
@@ -2190,7 +2254,7 @@ BiosKeyboardRegisterKeyNotify (
   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
   IN EFI_KEY_DATA                       *KeyData,\r
   IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,\r
   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
   IN EFI_KEY_DATA                       *KeyData,\r
   IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,\r
-  OUT EFI_HANDLE                        *NotifyHandle\r
+  OUT VOID                              **NotifyHandle\r
   )\r
 {\r
   EFI_STATUS                            Status;\r
   )\r
 {\r
   EFI_STATUS                            Status;\r
@@ -2223,7 +2287,7 @@ BiosKeyboardRegisterKeyNotify (
                       );\r
     if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
       if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
                       );\r
     if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
       if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
-        *NotifyHandle = CurrentNotify->NotifyHandle;        \r
+        *NotifyHandle = CurrentNotify;\r
         Status = EFI_SUCCESS;\r
         goto Exit;\r
       }\r
         Status = EFI_SUCCESS;\r
         goto Exit;\r
       }\r
@@ -2242,11 +2306,10 @@ BiosKeyboardRegisterKeyNotify (
 \r
   NewNotify->Signature         = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
   NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
 \r
   NewNotify->Signature         = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
   NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
-  NewNotify->NotifyHandle      = (EFI_HANDLE) NewNotify;\r
   CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
   InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);\r
 \r
   CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
   InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);\r
 \r
-  *NotifyHandle                = NewNotify->NotifyHandle;  \r
+  *NotifyHandle                = NewNotify;\r
   Status                       = EFI_SUCCESS;\r
   \r
 Exit:\r
   Status                       = EFI_SUCCESS;\r
   \r
 Exit:\r
@@ -2271,7 +2334,7 @@ EFI_STATUS
 EFIAPI\r
 BiosKeyboardUnregisterKeyNotify (\r
   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
 EFIAPI\r
 BiosKeyboardUnregisterKeyNotify (\r
   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
-  IN EFI_HANDLE                         NotificationHandle\r
+  IN VOID                               *NotificationHandle\r
   )\r
 {\r
   EFI_STATUS                            Status;\r
   )\r
 {\r
   EFI_STATUS                            Status;\r
@@ -2296,7 +2359,7 @@ BiosKeyboardUnregisterKeyNotify (
   //\r
   // Enter critical section\r
   //\r
   //\r
   // Enter critical section\r
   //\r
-  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);  \r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
 \r
   for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
     CurrentNotify = CR (\r
 \r
   for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
     CurrentNotify = CR (\r
@@ -2305,7 +2368,7 @@ BiosKeyboardUnregisterKeyNotify (
                       NotifyEntry, \r
                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
                       );    \r
                       NotifyEntry, \r
                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
                       );    \r
-    if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+    if (CurrentNotify == NotificationHandle) {\r
       //\r
       // Remove the notification function from NotifyList and free resources\r
       //\r
       //\r
       // Remove the notification function from NotifyList and free resources\r
       //\r