]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
IntelFrameworkModulePkg: Clean up source files
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdCtrller.c
index 1b6ed43bd374c104d08ac9b6b53e422af410e728..78c4e3b3919da5e9754e98cbd406a56bb9554225 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Routines that access 8042 keyboard controller\r
 \r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Ps2Keyboard.h"\r
 \r
 struct {\r
-  UINT16  ScanCode;             ///< follows value defined in Scan Code Set1\r
+  UINT  ScanCode;             ///< follows value defined in Scan Code Set1\r
   UINT16  EfiScanCode;\r
   CHAR16  UnicodeChar;\r
   CHAR16  ShiftUnicodeChar;\r
@@ -537,25 +537,19 @@ ConvertKeyboardScanCodeToEfiKey[] = {
     SCAN_NULL,\r
     0x0000,\r
     0x0000\r
-  },  \r
+  },\r
   {\r
     0x5C,  //Right LOGO\r
     SCAN_NULL,\r
     0x0000,\r
     0x0000\r
-  },  \r
+  },\r
   {\r
     0x5D,  //Menu key\r
     SCAN_NULL,\r
     0x0000,\r
     0x0000\r
-  },  \r
-  {\r
-    SCANCODE_PAUSE_MAKE,  //Pause key\r
-    SCAN_PAUSE,\r
-    0x0000,\r
-    0x0000\r
-  }, \r
+  },\r
   {\r
     TABLE_END,\r
     TABLE_END,\r
@@ -575,7 +569,7 @@ BOOLEAN          mEnableMouseInterface;
 \r
 /**\r
   Return the count of scancode in the queue.\r
-  \r
+\r
   @param Queue     Pointer to instance of SCAN_CODE_QUEUE.\r
 \r
   @return          Count of the scancode.\r
@@ -596,7 +590,7 @@ GetScancodeBufCount (
   Read several bytes from the scancode buffer without removing them.\r
   This function is called to see if there are enough bytes of scancode\r
   representing a single key.\r
-  \r
+\r
   @param Queue     Pointer to instance of SCAN_CODE_QUEUE.\r
   @param Count     Number of bytes to be read\r
   @param Buf       Store the results\r
@@ -630,31 +624,11 @@ GetScancodeBufHead (
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Push one byte to the scancode buffer.\r
-\r
-  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.\r
-  @param Scancode  The byte to push.\r
-**/\r
-VOID\r
-PushScancodeBufTail (\r
-  IN  SCAN_CODE_QUEUE       *Queue,\r
-  IN  UINT8                 Scancode\r
-  )\r
-{\r
-  if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {\r
-    return;\r
-  }\r
-\r
-  Queue->Buffer[Queue->Tail] = Scancode;\r
-  Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;\r
-}\r
-\r
 /**\r
 \r
   Read & remove several bytes from the scancode buffer.\r
   This function is usually called after GetScancodeBufHead()\r
-  \r
+\r
   @param Queue     Pointer to instance of SCAN_CODE_QUEUE.\r
   @param Count     Number of bytes to be read\r
   @param Buf       Store the results\r
@@ -666,7 +640,7 @@ EFI_STATUS
 PopScancodeBufHead (\r
   IN  SCAN_CODE_QUEUE       *Queue,\r
   IN  UINTN                 Count,\r
-  OUT UINT8                 *Buf\r
+  OUT UINT8                 *Buf OPTIONAL\r
   )\r
 {\r
   UINTN                     Index;\r
@@ -681,18 +655,40 @@ PopScancodeBufHead (
   // Retrieve and remove the values\r
   //\r
   for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {\r
-    Buf[Index] = Queue->Buffer[Queue->Head];\r
+    if (Buf != NULL) {\r
+      Buf[Index] = Queue->Buffer[Queue->Head];\r
+    }\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Push one byte to the scancode buffer.\r
+\r
+  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.\r
+  @param Scancode  The byte to push.\r
+**/\r
+VOID\r
+PushScancodeBufTail (\r
+  IN  SCAN_CODE_QUEUE       *Queue,\r
+  IN  UINT8                 Scancode\r
+  )\r
+{\r
+  if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {\r
+    PopScancodeBufHead (Queue, 1, NULL);\r
+  }\r
+\r
+  Queue->Buffer[Queue->Tail] = Scancode;\r
+  Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;\r
+}\r
+\r
 /**\r
   Read data register .\r
 \r
   @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
 \r
-  @return return the value \r
+  @return return the value\r
 \r
 **/\r
 UINT8\r
@@ -793,7 +789,7 @@ KeyWriteCommandRegister (
 \r
   @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
   @param ErrMsg    Unicode string of error message\r
-  \r
+\r
 **/\r
 VOID\r
 KeyboardError (\r
@@ -959,9 +955,9 @@ KeyboardWrite (
   Issue keyboard command.\r
 \r
   @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
-  @param Data      The buff holding the command \r
+  @param Data      The buff holding the command\r
 \r
-  @retval EFI_TIMEOUT Keyboard is not ready to issuing \r
+  @retval EFI_TIMEOUT Keyboard is not ready to issuing\r
   @retval EFI_SUCCESS Success to issue keyboard command\r
 \r
 **/\r
@@ -1027,7 +1023,7 @@ KeyboardCommand (
 \r
   @retval EFI_TIMEOUT Fail to get specific value in given time\r
   @retval EFI_SUCCESS Success to get specific value in given time.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 KeyboardWaitForValue (\r
@@ -1096,7 +1092,7 @@ KeyboardWaitForValue (
   indicators in ConsoleIn.\r
 \r
   @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
-  \r
+\r
   @return status of updating keyboard register\r
 \r
 **/\r
@@ -1144,6 +1140,38 @@ UpdateStatusLights (
   return Status;\r
 }\r
 \r
+/**\r
+  Initialize the key state.\r
+\r
+  @param  ConsoleIn     The KEYBOARD_CONSOLE_IN_DEV instance.\r
+  @param  KeyState      A pointer to receive the key state information.\r
+**/\r
+VOID\r
+InitializeKeyState (\r
+  IN  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
+  OUT EFI_KEY_STATE           *KeyState\r
+  )\r
+{\r
+  KeyState->KeyShiftState  = EFI_SHIFT_STATE_VALID\r
+                           | (ConsoleIn->LeftCtrl   ? EFI_LEFT_CONTROL_PRESSED  : 0)\r
+                           | (ConsoleIn->RightCtrl  ? EFI_RIGHT_CONTROL_PRESSED : 0)\r
+                           | (ConsoleIn->LeftAlt    ? EFI_LEFT_ALT_PRESSED      : 0)\r
+                           | (ConsoleIn->RightAlt   ? EFI_RIGHT_ALT_PRESSED     : 0)\r
+                           | (ConsoleIn->LeftShift  ? EFI_LEFT_SHIFT_PRESSED    : 0)\r
+                           | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED   : 0)\r
+                           | (ConsoleIn->LeftLogo   ? EFI_LEFT_LOGO_PRESSED     : 0)\r
+                           | (ConsoleIn->RightLogo  ? EFI_RIGHT_LOGO_PRESSED    : 0)\r
+                           | (ConsoleIn->Menu       ? EFI_MENU_KEY_PRESSED      : 0)\r
+                           | (ConsoleIn->SysReq     ? EFI_SYS_REQ_PRESSED       : 0)\r
+                           ;\r
+  KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID\r
+                           | (ConsoleIn->CapsLock   ? EFI_CAPS_LOCK_ACTIVE :   0)\r
+                           | (ConsoleIn->NumLock    ? EFI_NUM_LOCK_ACTIVE :    0)\r
+                           | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0)\r
+                           | (ConsoleIn->IsSupportPartialKey ? EFI_KEY_STATE_EXPOSED : 0)\r
+                           ;\r
+}\r
+\r
 /**\r
   Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec.\r
 \r
@@ -1159,53 +1187,48 @@ KeyGetchar (
 {\r
   EFI_STATUS                     Status;\r
   UINT16                         ScanCode;\r
-  BOOLEAN                        Extended;\r
-  BOOLEAN                        Extended1;\r
+  BOOLEAN                        Extend0;\r
+  BOOLEAN                        Extend1;\r
   UINTN                          Index;\r
   EFI_KEY_DATA                   KeyData;\r
   LIST_ENTRY                     *Link;\r
   KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;\r
   //\r
-  // 6 bytes most\r
+  // 3 bytes most\r
   //\r
-  UINT8                          ScancodeArr[6];\r
+  UINT8                          ScancodeArr[3];\r
   UINT32                         ScancodeArrPos;\r
-  \r
+\r
   //\r
   // Check if there are enough bytes of scancode representing a single key\r
   // available in the buffer\r
   //\r
   while (TRUE) {\r
-    Extended          = FALSE;\r
-    Extended1         = FALSE;\r
-    Status            = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 1, ScancodeArr);\r
-    //\r
-    // point to the current position in ScancodeArr\r
-    //\r
-    ScancodeArrPos    = 0;\r
+    Extend0        = FALSE;\r
+    Extend1        = FALSE;\r
+    ScancodeArrPos = 0;\r
+    Status  = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);\r
     if (EFI_ERROR (Status)) {\r
       return ;\r
     }\r
 \r
-    if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {\r
-      Extended        = TRUE;\r
-      Status          = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 2, ScancodeArr);\r
-      ScancodeArrPos  = 1;\r
+    if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) {\r
+      //\r
+      // E0 to look ahead 2 bytes\r
+      //\r
+      Extend0 = TRUE;\r
+      ScancodeArrPos = 1;\r
+      Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);\r
       if (EFI_ERROR (Status)) {\r
         return ;\r
       }\r
-    }\r
-    //\r
-    // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5\r
-    // if present, ignore them\r
-    //\r
-    if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {\r
-      Extended1       = TRUE;\r
+    } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {\r
       //\r
-      // Try to read the whole bytes of scancode for PAUSE key\r
+      // E1 to look ahead 3 bytes\r
       //\r
-      Status          = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 6, ScancodeArr);\r
-      ScancodeArrPos  = 5;\r
+      Extend1 = TRUE;\r
+      ScancodeArrPos = 2;\r
+      Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);\r
       if (EFI_ERROR (Status)) {\r
         return ;\r
       }\r
@@ -1214,88 +1237,113 @@ KeyGetchar (
     // if we reach this position, scancodes for a key is in buffer now,pop them\r
     //\r
     Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);\r
-    if (EFI_ERROR (Status)) {\r
-      return ;\r
-    }\r
+    ASSERT_EFI_ERROR (Status);\r
 \r
-    if (!Extended1) {\r
-      //\r
-      // store the last available byte, this byte of scancode will be checked\r
-      //\r
-      ScanCode = ScancodeArr[ScancodeArrPos];\r
-      \r
+    //\r
+    // store the last available byte, this byte of scancode will be checked\r
+    //\r
+    ScanCode = ScancodeArr[ScancodeArrPos];\r
+\r
+    if (!Extend1) {\r
       //\r
       // Check for special keys and update the driver state.\r
       //\r
       switch (ScanCode) {\r
-      \r
+\r
       case SCANCODE_CTRL_MAKE:\r
-        ConsoleIn->Ctrl = TRUE;\r
+        if (Extend0) {\r
+          ConsoleIn->RightCtrl = TRUE;\r
+        } else {\r
+          ConsoleIn->LeftCtrl  = TRUE;\r
+        }\r
         break;\r
-      \r
       case SCANCODE_CTRL_BREAK:\r
-        ConsoleIn->Ctrl = FALSE;\r
+        if (Extend0) {\r
+          ConsoleIn->RightCtrl = FALSE;\r
+        } else {\r
+          ConsoleIn->LeftCtrl  = FALSE;\r
+        }\r
         break;\r
-      \r
+\r
       case SCANCODE_ALT_MAKE:\r
-        ConsoleIn->Alt = TRUE;\r
+          if (Extend0) {\r
+            ConsoleIn->RightAlt = TRUE;\r
+          } else {\r
+            ConsoleIn->LeftAlt  = TRUE;\r
+          }\r
         break;\r
-      \r
       case SCANCODE_ALT_BREAK:\r
-        ConsoleIn->Alt = FALSE;\r
+          if (Extend0) {\r
+            ConsoleIn->RightAlt = FALSE;\r
+          } else {\r
+            ConsoleIn->LeftAlt  = FALSE;\r
+          }\r
         break;\r
-      \r
+\r
       case SCANCODE_LEFT_SHIFT_MAKE:\r
-        if (!Extended) {\r
-          ConsoleIn->Shift     = TRUE;\r
-          ConsoleIn->LeftShift = TRUE;\r
-        }      \r
-        break;\r
-      case SCANCODE_RIGHT_SHIFT_MAKE:\r
-        if (!Extended) {\r
-          ConsoleIn->Shift = TRUE;\r
-          ConsoleIn->RightShift = TRUE;\r
+        //\r
+        // To avoid recognize PRNT_SCRN key as a L_SHIFT key\r
+        // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code.\r
+        // If it the second byte of the PRNT_ScRN skip it.\r
+        //\r
+        if (!Extend0) {\r
+          ConsoleIn->LeftShift  = TRUE;\r
+          break;\r
         }\r
-        break;\r
-      \r
+        continue;\r
+\r
       case SCANCODE_LEFT_SHIFT_BREAK:\r
-        if (!Extended) {\r
-          ConsoleIn->Shift     = FALSE;\r
+        if (!Extend0) {\r
           ConsoleIn->LeftShift = FALSE;\r
-        } else {\r
-          ConsoleIn->SysReq    = FALSE;\r
-        }      \r
+        }\r
+        break;\r
+\r
+      case SCANCODE_RIGHT_SHIFT_MAKE:\r
+        ConsoleIn->RightShift = TRUE;\r
         break;\r
       case SCANCODE_RIGHT_SHIFT_BREAK:\r
-        if (!Extended) {\r
-          ConsoleIn->Shift = FALSE;\r
-          ConsoleIn->RightShift = FALSE;\r
-        }\r
+        ConsoleIn->RightShift = FALSE;\r
         break;\r
-      \r
+\r
       case SCANCODE_LEFT_LOGO_MAKE:\r
         ConsoleIn->LeftLogo = TRUE;\r
-        break;    \r
+        break;\r
       case SCANCODE_LEFT_LOGO_BREAK:\r
         ConsoleIn->LeftLogo = FALSE;\r
-        break;          \r
+        break;\r
+\r
       case SCANCODE_RIGHT_LOGO_MAKE:\r
         ConsoleIn->RightLogo = TRUE;\r
         break;\r
       case SCANCODE_RIGHT_LOGO_BREAK:\r
         ConsoleIn->RightLogo = FALSE;\r
-        break;      \r
+        break;\r
+\r
       case SCANCODE_MENU_MAKE:\r
         ConsoleIn->Menu = TRUE;\r
         break;\r
       case SCANCODE_MENU_BREAK:\r
         ConsoleIn->Menu = FALSE;\r
-        break;      \r
+        break;\r
+\r
       case SCANCODE_SYS_REQ_MAKE:\r
-        if (Extended) {\r
+        if (Extend0) {\r
           ConsoleIn->SysReq = TRUE;\r
         }\r
         break;\r
+      case SCANCODE_SYS_REQ_BREAK:\r
+        if (Extend0) {\r
+          ConsoleIn->SysReq = FALSE;\r
+        }\r
+        break;\r
+\r
+      case SCANCODE_SYS_REQ_MAKE_WITH_ALT:\r
+        ConsoleIn->SysReq = TRUE;\r
+        break;\r
+      case SCANCODE_SYS_REQ_BREAK_WITH_ALT:\r
+        ConsoleIn->SysReq = FALSE;\r
+        break;\r
+\r
       case SCANCODE_CAPS_LOCK_MAKE:\r
         ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;\r
         UpdateStatusLights (ConsoleIn);\r
@@ -1305,65 +1353,86 @@ KeyGetchar (
         UpdateStatusLights (ConsoleIn);\r
         break;\r
       case SCANCODE_SCROLL_LOCK_MAKE:\r
-        ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;\r
-        UpdateStatusLights (ConsoleIn);\r
-        break;\r
-      }\r
-      //\r
-      // If this is above the valid range, ignore it\r
-      //\r
-      if (ScanCode >= SCANCODE_MAX_MAKE) {\r
-        continue;\r
-      } else {\r
+        if (!Extend0) {\r
+          ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;\r
+          UpdateStatusLights (ConsoleIn);\r
+        }\r
         break;\r
       }\r
+    }\r
+\r
+    //\r
+    // If this is above the valid range, ignore it\r
+    //\r
+    if (ScanCode >= SCANCODE_MAX_MAKE) {\r
+      continue;\r
     } else {\r
-      //\r
-      // Store the last 2 available byte to check if it is Pause key\r
-      //\r
-      ScanCode = (UINT16) (ScancodeArr[ScancodeArrPos] + (ScancodeArr[ScancodeArrPos - 1] << 8));\r
-      if (ScanCode == SCANCODE_PAUSE_MAKE) {\r
-        break;\r
-      }\r
+      break;\r
     }\r
   }\r
 \r
   //\r
   // Handle Ctrl+Alt+Del hotkey\r
   //\r
-  if (ConsoleIn->Alt && ConsoleIn->Ctrl && ScanCode == SCANCODE_DELETE_MAKE) {\r
+  if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) &&\r
+      (ConsoleIn->LeftAlt  || ConsoleIn->RightAlt ) &&\r
+      ScanCode == SCANCODE_DELETE_MAKE\r
+     ) {\r
     gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
   }\r
 \r
-  KeyData.Key.ScanCode            = SCAN_NULL;\r
-  KeyData.Key.UnicodeChar         = CHAR_NULL;\r
-  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
-  KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+  //\r
+  // Save the Shift/Toggle state\r
+  //\r
+  InitializeKeyState (ConsoleIn, &KeyData.KeyState);\r
+  KeyData.Key.ScanCode    = SCAN_NULL;\r
+  KeyData.Key.UnicodeChar = CHAR_NULL;\r
 \r
   //\r
-  // Treat Numeric Key Pad "/" specially\r
+  // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix\r
   //\r
-  if (Extended && ScanCode == 0x35) {\r
+  if (Extend0 && ScanCode == 0x35) {\r
     KeyData.Key.UnicodeChar = L'/';\r
     KeyData.Key.ScanCode    = SCAN_NULL;\r
+\r
+  //\r
+  // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix\r
+  //\r
+  } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) {\r
+    KeyData.Key.UnicodeChar = CHAR_NULL;\r
+    KeyData.Key.ScanCode    = SCAN_PAUSE;\r
+\r
+  //\r
+  // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix\r
+  //\r
+  } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) {\r
+    KeyData.Key.UnicodeChar = CHAR_NULL;\r
+    KeyData.Key.ScanCode    = SCAN_PAUSE;\r
+\r
+  //\r
+  // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix\r
+  //\r
+  } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) {\r
+    KeyData.Key.UnicodeChar = CHAR_NULL;\r
+    KeyData.Key.ScanCode    = SCAN_NULL;\r
+\r
+  //\r
+  // Except the above special case, all others can be handled by convert table\r
+  //\r
   } else {\r
-    //\r
-    // Convert Keyboard ScanCode into an EFI Key\r
-    //\r
-    for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {\r
+    for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) {\r
       if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {\r
         KeyData.Key.ScanCode    = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;\r
         KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\r
 \r
-        if (ConsoleIn->Shift && \r
+        if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) &&\r
             (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {\r
           KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;\r
           //\r
           // Need not return associated shift state if a class of printable characters that\r
           // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
           //\r
-          ConsoleIn->LeftShift  = FALSE;\r
-          ConsoleIn->RightShift = FALSE;\r
+          KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r
         }\r
         //\r
         // alphabetic key is affected by CapsLock State\r
@@ -1384,79 +1453,40 @@ KeyGetchar (
   // distinguish numeric key pad keys' 'up symbol' and 'down symbol'\r
   //\r
   if (ScanCode >= 0x47 && ScanCode <= 0x53) {\r
-    if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {\r
+    if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) {\r
       KeyData.Key.ScanCode = SCAN_NULL;\r
     } else if (ScanCode != 0x4a && ScanCode != 0x4e) {\r
       KeyData.Key.UnicodeChar = CHAR_NULL;\r
     }\r
   }\r
+\r
   //\r
   // If the key can not be converted then just return.\r
   //\r
   if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {\r
-    return ;\r
-  }\r
-\r
-  //\r
-  // Save the Shift/Toggle state\r
-  //\r
-  if (ConsoleIn->Ctrl) {\r
-    KeyData.KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;\r
-  }                                    \r
-  if (ConsoleIn->Alt) {                \r
-    KeyData.KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;\r
-  }                                    \r
-  if (ConsoleIn->LeftShift) {          \r
-    KeyData.KeyState.KeyShiftState  |= EFI_LEFT_SHIFT_PRESSED;\r
-  }                                    \r
-  if (ConsoleIn->RightShift) {         \r
-    KeyData.KeyState.KeyShiftState  |= EFI_RIGHT_SHIFT_PRESSED;\r
-  }                                    \r
-  if (ConsoleIn->LeftLogo) {           \r
-    KeyData.KeyState.KeyShiftState  |= EFI_LEFT_LOGO_PRESSED;\r
-  }                                    \r
-  if (ConsoleIn->RightLogo) {          \r
-    KeyData.KeyState.KeyShiftState  |= EFI_RIGHT_LOGO_PRESSED;\r
-  }                                    \r
-  if (ConsoleIn->Menu) {               \r
-    KeyData.KeyState.KeyShiftState  |= EFI_MENU_KEY_PRESSED;\r
-  }                                    \r
-  if (ConsoleIn->SysReq) {             \r
-    KeyData.KeyState.KeyShiftState  |= EFI_SYS_REQ_PRESSED;\r
-  }  \r
-  if (ConsoleIn->CapsLock) {\r
-    KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
-  }\r
-  if (ConsoleIn->NumLock) {\r
-    KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
-  }\r
-  if (ConsoleIn->ScrollLock) {\r
-    KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
+    if (!ConsoleIn->IsSupportPartialKey) {\r
+      return ;\r
+    }\r
   }\r
 \r
   //\r
-  // Invoke notification functions if exist\r
+  // Signal KeyNotify process event if this key pressed matches any key registered.\r
   //\r
   for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {\r
     CurrentNotify = CR (\r
-                      Link, \r
-                      KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
-                      NotifyEntry, \r
+                      Link,\r
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+                      NotifyEntry,\r
                       KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
                       );\r
-    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { \r
-      CurrentNotify->KeyNotificationFn (&KeyData);\r
-    }\r
-  }\r
-  \r
-  //\r
-  // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
-  //\r
-  if (ConsoleIn->Ctrl) {\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
+    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+      //\r
+      // The key notification function needs to run at TPL_CALLBACK\r
+      // while current TPL is TPL_NOTIFY. It will be invoked in\r
+      // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.\r
+      //\r
+      PushEfikeyBufTail (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);\r
+      gBS->SignalEvent (ConsoleIn->KeyNotifyProcessEvent);\r
     }\r
   }\r
 \r
@@ -1464,7 +1494,7 @@ KeyGetchar (
 }\r
 \r
 /**\r
-  Perform 8042 controller and keyboard Initialization.  \r
+  Perform 8042 controller and keyboard Initialization.\r
   If ExtendedVerification is TRUE, do additional test for\r
   the keyboard interface\r
 \r
@@ -1509,16 +1539,18 @@ InitKeyboard (
   // Perform a read to cleanup the Status Register's\r
   // output buffer full bits within MAX TRY times\r
   //\r
-  while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {\r
-    Status = KeyboardRead (ConsoleIn, &CommandByte);\r
-    TryTime ++;\r
-  }\r
-  //\r
-  // Exceed the max try times. The device may be error.\r
-  //\r
-  if (TryTime == KEYBOARD_MAX_TRY) {\r
-       Status = EFI_DEVICE_ERROR;\r
-       goto Done;\r
+  if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {\r
+    while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {\r
+      Status = KeyboardRead (ConsoleIn, &CommandByte);\r
+      TryTime ++;\r
+    }\r
+    //\r
+    // Exceed the max try times. The device may be error.\r
+    //\r
+    if (TryTime == KEYBOARD_MAX_TRY) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Done;\r
+    }\r
   }\r
   //\r
   // We should disable mouse interface during the initialization process\r
@@ -1533,34 +1565,37 @@ InitKeyboard (
   // time initialization\r
   //\r
   if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {\r
-    //\r
-    // 8042 controller is already setup (by myself or by mouse driver):\r
-    //   See whether mouse interface is already enabled\r
-    //   which determines whether we should enable it later\r
-    //\r
-    //\r
-    // Read the command byte of 8042 controller\r
-    //\r
-    Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);\r
-    if (EFI_ERROR (Status)) {\r
-      KeyboardError (ConsoleIn, L"\n\r");\r
-      goto Done;\r
-    }\r
+    if (!PcdGetBool (PcdFastPS2Detection)) {\r
+      //\r
+      // 8042 controller is already setup (by myself or by mouse driver):\r
+      //   See whether mouse interface is already enabled\r
+      //   which determines whether we should enable it later\r
+      //\r
+      //\r
+      // Read the command byte of 8042 controller\r
+      //\r
+      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);\r
+      if (EFI_ERROR (Status)) {\r
+        KeyboardError (ConsoleIn, L"\n\r");\r
+        goto Done;\r
+      }\r
 \r
-    Status = KeyboardRead (ConsoleIn, &CommandByte);\r
-    if (EFI_ERROR (Status)) {\r
-      KeyboardError (ConsoleIn, L"\n\r");\r
-      goto Done;\r
-    }\r
-    //\r
-    // Test the mouse enabling bit\r
-    //\r
-    if ((CommandByte & 0x20) != 0) {\r
-      mEnableMouseInterface = FALSE;\r
+      Status = KeyboardRead (ConsoleIn, &CommandByte);\r
+      if (EFI_ERROR (Status)) {\r
+        KeyboardError (ConsoleIn, L"\n\r");\r
+        goto Done;\r
+      }\r
+      //\r
+      // Test the mouse enabling bit\r
+      //\r
+      if ((CommandByte & 0x20) != 0) {\r
+        mEnableMouseInterface = FALSE;\r
+      } else {\r
+        mEnableMouseInterface = TRUE;\r
+      }\r
     } else {\r
-      mEnableMouseInterface = TRUE;\r
+      mEnableMouseInterface = FALSE;\r
     }\r
-\r
   } else {\r
     //\r
     // 8042 controller is not setup yet:\r
@@ -1570,36 +1605,38 @@ InitKeyboard (
     //\r
     // Disable keyboard and mouse interfaces\r
     //\r
-    Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);\r
-    if (EFI_ERROR (Status)) {\r
-      KeyboardError (ConsoleIn, L"\n\r");\r
-      goto Done;\r
-    }\r
+    if (!PcdGetBool (PcdFastPS2Detection)) {\r
+      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);\r
+      if (EFI_ERROR (Status)) {\r
+        KeyboardError (ConsoleIn, L"\n\r");\r
+        goto Done;\r
+      }\r
 \r
-    Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);\r
-    if (EFI_ERROR (Status)) {\r
-      KeyboardError (ConsoleIn, L"\n\r");\r
-      goto Done;\r
-    }\r
+      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);\r
+      if (EFI_ERROR (Status)) {\r
+        KeyboardError (ConsoleIn, L"\n\r");\r
+        goto Done;\r
+      }\r
 \r
-    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-      EFI_PROGRESS_CODE,\r
-      EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,\r
-      ConsoleIn->DevicePath\r
-      );\r
-    //\r
-    // 8042 Controller Self Test\r
-    //\r
-    Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);\r
-    if (EFI_ERROR (Status)) {\r
-      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
-      goto Done;\r
-    }\r
+      REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+        EFI_PROGRESS_CODE,\r
+        EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,\r
+        ConsoleIn->DevicePath\r
+        );\r
+      //\r
+      // 8042 Controller Self Test\r
+      //\r
+      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);\r
+      if (EFI_ERROR (Status)) {\r
+        KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
+        goto Done;\r
+      }\r
 \r
-    Status = KeyboardWaitForValue (ConsoleIn, 0x55);\r
-    if (EFI_ERROR (Status)) {\r
-      KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");\r
-      goto Done;\r
+      Status = KeyboardWaitForValue (ConsoleIn, 0x55);\r
+      if (EFI_ERROR (Status)) {\r
+        KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");\r
+        goto Done;\r
+      }\r
     }\r
     //\r
     // Don't enable mouse interface later\r
@@ -1648,27 +1685,31 @@ InitKeyboard (
   ConsoleIn->ScancodeQueue.Tail = 0;\r
   ConsoleIn->EfiKeyQueue.Head   = 0;\r
   ConsoleIn->EfiKeyQueue.Tail   = 0;\r
+  ConsoleIn->EfiKeyQueueForNotify.Head = 0;\r
+  ConsoleIn->EfiKeyQueueForNotify.Tail = 0;\r
 \r
   //\r
   // Reset the status indicators\r
   //\r
-  ConsoleIn->Ctrl       = FALSE;\r
-  ConsoleIn->Alt        = FALSE;\r
-  ConsoleIn->Shift      = FALSE;\r
   ConsoleIn->CapsLock   = FALSE;\r
   ConsoleIn->NumLock    = FALSE;\r
   ConsoleIn->ScrollLock = FALSE;\r
+  ConsoleIn->LeftCtrl   = FALSE;\r
+  ConsoleIn->RightCtrl  = FALSE;\r
+  ConsoleIn->LeftAlt    = FALSE;\r
+  ConsoleIn->RightAlt   = FALSE;\r
   ConsoleIn->LeftShift  = FALSE;\r
   ConsoleIn->RightShift = FALSE;\r
   ConsoleIn->LeftLogo   = FALSE;\r
   ConsoleIn->RightLogo  = FALSE;\r
   ConsoleIn->Menu       = FALSE;\r
-  ConsoleIn->SysReq     = FALSE;  \r
+  ConsoleIn->SysReq     = FALSE;\r
 \r
+  ConsoleIn->IsSupportPartialKey = FALSE;\r
   //\r
-  // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
+  // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
   // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected\r
-  // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,\r
+  // to system. So we only do the real resetting for keyboard when user asks and there is a real KB connected t system,\r
   // and normally during booting an OS, it's skipped.\r
   //\r
   if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {\r
@@ -1853,34 +1894,37 @@ CheckKeyboardConnect (
   EFI_STATUS     Status;\r
   UINTN          WaitForValueTimeOutBcakup;\r
 \r
-  Status = EFI_SUCCESS;\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
-             ConsoleIn,\r
-             KEYBOARD_KBEN\r
-             );\r
+  if (!PcdGetBool (PcdFastPS2Detection)) {\r
+    Status = KeyboardWrite (\r
+               ConsoleIn,\r
+               KEYBOARD_KBEN\r
+               );\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
-  //\r
-  // wait for 1s\r
-  //\r
-  WaitForValueTimeOutBcakup = mWaitForValueTimeOut;\r
-  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
-  Status = KeyboardWaitForValue (\r
-             ConsoleIn,\r
-             KEYBOARD_CMDECHO_ACK\r
-             );\r
-  mWaitForValueTimeOut = WaitForValueTimeOutBcakup;\r
+    if (EFI_ERROR (Status)) {\r
+      return FALSE;\r
+    }\r
+    //\r
+    // wait for 1s\r
+    //\r
+    WaitForValueTimeOutBcakup = mWaitForValueTimeOut;\r
+    mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
+    Status = KeyboardWaitForValue (\r
+               ConsoleIn,\r
+               KEYBOARD_CMDECHO_ACK\r
+               );\r
+    mWaitForValueTimeOut = WaitForValueTimeOutBcakup;\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
+    if (EFI_ERROR (Status)) {\r
+      return FALSE;\r
+    }\r
 \r
-  return TRUE;\r
+    return TRUE;\r
+  } else {\r
+    return TRUE;\r
+  }\r
 }\r
 \r