]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
Fix the PS2 keyboard driver to call hotkey callback even no one is calling ReadKeyStroke
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdCtrller.c
index aadc1bf2aeadf4da709ac35769c490aa66e464c6..fa0f53b7422065aa6f30b752278af52b1de0c6b7 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Routines that access 8042 keyboard controller\r
 \r
 /** @file\r
   Routines that access 8042 keyboard controller\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2011, 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
 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
@@ -558,7 +558,6 @@ ConvertKeyboardScanCodeToEfiKey[] = {
   },\r
 };\r
 \r
   },\r
 };\r
 \r
-\r
 //\r
 // The WaitForValue time out\r
 //\r
 //\r
 // The WaitForValue time out\r
 //\r
@@ -566,6 +565,122 @@ UINTN  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
 \r
 BOOLEAN          mEnableMouseInterface;\r
 \r
 \r
 BOOLEAN          mEnableMouseInterface;\r
 \r
+\r
+\r
+/**\r
+  Return the count of scancode in the queue.\r
+  \r
+  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.\r
+\r
+  @return          Count of the scancode.\r
+**/\r
+UINTN\r
+GetScancodeBufCount (\r
+  IN SCAN_CODE_QUEUE       *Queue\r
+  )\r
+{\r
+  if (Queue->Head <= Queue->Tail) {\r
+    return Queue->Tail - Queue->Head;\r
+  } else {\r
+    return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head;\r
+  }\r
+}\r
+\r
+/**\r
+  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
+  @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
+\r
+  @retval EFI_SUCCESS   success to scan the keyboard code\r
+  @retval EFI_NOT_READY invalid parameter\r
+**/\r
+EFI_STATUS\r
+GetScancodeBufHead (\r
+  IN  SCAN_CODE_QUEUE        *Queue,\r
+  IN  UINTN                  Count,\r
+  OUT UINT8                  *Buf\r
+  )\r
+{\r
+  UINTN                      Index;\r
+  UINTN                      Pos;\r
+\r
+  //\r
+  // check the valid range of parameter 'Count'\r
+  //\r
+  if (GetScancodeBufCount (Queue) < Count) {\r
+    return EFI_NOT_READY;\r
+  }\r
+  //\r
+  // retrieve the values\r
+  //\r
+  for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {\r
+    Buf[Index] = Queue->Buffer[Pos];\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
+    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
+  @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
+\r
+  @retval EFI_SUCCESS success to scan the keyboard code\r
+  @retval EFI_NOT_READY invalid parameter\r
+**/\r
+EFI_STATUS\r
+PopScancodeBufHead (\r
+  IN  SCAN_CODE_QUEUE       *Queue,\r
+  IN  UINTN                 Count,\r
+  OUT UINT8                 *Buf\r
+  )\r
+{\r
+  UINTN                     Index;\r
+\r
+  //\r
+  // Check the valid range of parameter 'Count'\r
+  //\r
+  if (GetScancodeBufCount (Queue) < Count) {\r
+    return EFI_NOT_READY;\r
+  }\r
+  //\r
+  // 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
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Read data register .\r
 \r
 /**\r
   Read data register .\r
 \r
@@ -611,23 +726,14 @@ KeyWriteDataRegister (
   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
   IN UINT8                   Data\r
   )\r
   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
   IN UINT8                   Data\r
   )\r
-\r
 {\r
 {\r
-  EFI_ISA_IO_PROTOCOL                 *IsaIo;\r
-\r
-  //\r
-  // Use IsaIo protocol to perform IO operations\r
-  //\r
-  IsaIo = ConsoleIn->IsaIo;\r
-\r
-  IsaIo->Io.Write (\r
-              IsaIo,\r
-              EfiIsaIoWidthUint8,\r
-              ConsoleIn->DataRegisterAddress,\r
-              1,\r
-              &Data\r
-              );\r
-\r
+  ConsoleIn->IsaIo->Io.Write (\r
+                         ConsoleIn->IsaIo,\r
+                         EfiIsaIoWidthUint8,\r
+                         ConsoleIn->DataRegisterAddress,\r
+                         1,\r
+                         &Data\r
+                         );\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -643,24 +749,15 @@ KeyReadStatusRegister (
   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
   )\r
 {\r
   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
   )\r
 {\r
-  EFI_ISA_IO_PROTOCOL                 *IsaIo;\r
   UINT8                               Data;\r
   UINT8                               Data;\r
-\r
-  //\r
-  // Use IsaIo protocol to perform IO operations\r
-  //\r
-  IsaIo = ConsoleIn->IsaIo;\r
-\r
-  IsaIo->Io.Read (\r
-              IsaIo,\r
-              EfiIsaIoWidthUint8,\r
-              ConsoleIn->StatusRegisterAddress,\r
-              1,\r
-              &Data\r
-              );\r
-\r
+  ConsoleIn->IsaIo->Io.Read (\r
+                         ConsoleIn->IsaIo,\r
+                         EfiIsaIoWidthUint8,\r
+                         ConsoleIn->StatusRegisterAddress,\r
+                         1,\r
+                         &Data\r
+                         );\r
   return Data;\r
   return Data;\r
-\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -676,21 +773,13 @@ KeyWriteCommandRegister (
   IN UINT8                   Data\r
   )\r
 {\r
   IN UINT8                   Data\r
   )\r
 {\r
-  EFI_ISA_IO_PROTOCOL                 *IsaIo;\r
-\r
-  //\r
-  // Use IsaIo protocol to perform IO operations\r
-  //\r
-  IsaIo = ConsoleIn->IsaIo;\r
-\r
-  IsaIo->Io.Write (\r
-              IsaIo,\r
-              EfiIsaIoWidthUint8,\r
-              ConsoleIn->CommandRegisterAddress,\r
-              1,\r
-              &Data\r
-              );\r
-\r
+  ConsoleIn->IsaIo->Io.Write (\r
+                         ConsoleIn->IsaIo,\r
+                         EfiIsaIoWidthUint8,\r
+                         ConsoleIn->CommandRegisterAddress,\r
+                         1,\r
+                         &Data\r
+                         );\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -732,7 +821,7 @@ KeyboardTimerHandler (
   EFI_TPL                 OldTpl;\r
   KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
 \r
   EFI_TPL                 OldTpl;\r
   KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
 \r
-  ConsoleIn = Context;\r
+  ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
 \r
   //\r
   // Enter critical section\r
 \r
   //\r
   // Enter critical section\r
@@ -749,182 +838,27 @@ KeyboardTimerHandler (
 \r
   //\r
   // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that\r
 \r
   //\r
   // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that\r
-  // KB is not connected to system. If KB is not connected to system, driver will find there's  something\r
-  // error in the following code and wait for the input buffer empty, this waiting time shoulb be  short enough since\r
+  // KB is not connected to system. If KB is not connected to system, driver will find there's something\r
+  // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since\r
   // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
   // Just skip the 'resend' process simply.\r
   //\r
 \r
   // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
   // Just skip the 'resend' process simply.\r
   //\r
 \r
-  Data = 0;\r
-\r
-  //\r
-  // if there is no key present, just return\r
-  //\r
-  if ((KeyReadStatusRegister (Context) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) != KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {\r
+  while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) ==\r
+      KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA\r
+     ) {\r
     //\r
     //\r
-    // Leave critical section and return\r
+    // Read one byte of the scan code and store it into the memory buffer\r
     //\r
     //\r
-    gBS->RestoreTPL (OldTpl);\r
-\r
-    return ;\r
+    Data = KeyReadDataRegister (ConsoleIn);\r
+    PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data);\r
   }\r
   }\r
-  //\r
-  // Read one byte of the scan code and store it into the memory buffer\r
-  //\r
-  if (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT) {\r
-\r
-    Data = KeyReadDataRegister (Context);\r
-    //\r
-    // put the scancode into the memory scancode buffer\r
-    //\r
-    ConsoleIn->ScancodeBufCount++;\r
-    ConsoleIn->ScancodeBufEndPos++;\r
-    if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
-      ConsoleIn->ScancodeBufEndPos = 0;\r
-    }\r
+  KeyGetchar (ConsoleIn);\r
 \r
 \r
-    ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Data;\r
-\r
-    //\r
-    // Handle Alt+Ctrl+Del Key combination\r
-    //\r
-    switch (Data) {\r
-    case SCANCODE_CTRL_MAKE:\r
-      ConsoleIn->Ctrled = TRUE;\r
-      break;\r
-\r
-    case SCANCODE_CTRL_BREAK:\r
-      ConsoleIn->Ctrled = FALSE;\r
-      break;\r
-\r
-    case SCANCODE_ALT_MAKE:\r
-      ConsoleIn->Alted = TRUE;\r
-      break;\r
-\r
-    case SCANCODE_ALT_BREAK:\r
-      ConsoleIn->Alted = FALSE;\r
-      break;\r
-    }\r
-    //\r
-    // if Alt+Ctrl+Del, Reboot the System\r
-    //\r
-    if (ConsoleIn->Ctrled && ConsoleIn->Alted && Data == 0x53) {\r
-      gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
-    }\r
-  }\r
   //\r
   // Leave critical section and return\r
   //\r
   gBS->RestoreTPL (OldTpl);\r
   //\r
   // Leave critical section and return\r
   //\r
   gBS->RestoreTPL (OldTpl);\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  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
-  @param ConsoleIn  Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
-  @param Count      Number of bytes to be read\r
-  @param Buf        Store the results\r
-\r
-  @retval EFI_SUCCESS success to scan the keyboard code\r
-  @retval EFI_NOT_READY invalid parameter\r
-**/\r
-EFI_STATUS\r
-GetScancodeBufHead (\r
-  KEYBOARD_CONSOLE_IN_DEV    *ConsoleIn,\r
-  IN UINT32                  Count,\r
-  OUT UINT8                  *Buf\r
-  )\r
-{\r
-  UINT32  Index;\r
-  UINT32  Pos;\r
-\r
-  Index = 0;\r
-  Pos   = 0;\r
-\r
-  //\r
-  // check the valid range of parameter 'Count'\r
-  //\r
-  if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {\r
-    return EFI_NOT_READY;\r
-  }\r
-  //\r
-  // retrieve the values\r
-  //\r
-  for (Index = 0; Index < Count; Index++) {\r
-\r
-    if (Index == 0) {\r
-\r
-      Pos = ConsoleIn->ScancodeBufStartPos;\r
-    } else {\r
-\r
-      Pos = Pos + 1;\r
-      if (Pos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
-        Pos = 0;\r
-      }\r
-    }\r
-\r
-    Buf[Index] = ConsoleIn->ScancodeBuf[Pos];\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-\r
-  Read & remove several bytes from the scancode buffer.\r
-  This function is usually called after GetScancodeBufHead()\r
-\r
-  @param ConsoleIn  Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
-  @param Count      Number of bytes to be read\r
-  @param Buf        Store the results\r
-\r
-  @retval EFI_SUCCESS success to scan the keyboard code\r
-  @retval EFI_NOT_READY invalid parameter\r
-**/\r
-EFI_STATUS\r
-PopScancodeBufHead (\r
-  KEYBOARD_CONSOLE_IN_DEV   *ConsoleIn,\r
-  IN UINT32                 Count,\r
-  OUT UINT8                 *Buf\r
-  )\r
-{\r
-  UINT32  Index;\r
-\r
-  Index = 0;\r
-\r
-  //\r
-  // Check the valid range of parameter 'Count'\r
-  //\r
-  if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {\r
-    return EFI_NOT_READY;\r
-  }\r
-  //\r
-  // Retrieve and remove the values\r
-  //\r
-  for (Index = 0; Index < Count; Index++) {\r
-\r
-    if (Index != 0) {\r
-\r
-      ConsoleIn->ScancodeBufStartPos++;\r
-      if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
-        ConsoleIn->ScancodeBufStartPos = 0;\r
-      }\r
-    }\r
-\r
-    Buf[Index] = ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufStartPos];\r
-    ConsoleIn->ScancodeBufCount--;\r
-  }\r
-\r
-  ConsoleIn->ScancodeBufStartPos++;\r
-  if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
-    ConsoleIn->ScancodeBufStartPos = 0;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -1205,115 +1139,55 @@ UpdateStatusLights (
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Get scancode from scancode buffer\r
-  and translate into EFI-scancode and unicode defined by EFI spec\r
-  The function is always called in TPL_NOTIFY\r
+  Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec.\r
 \r
 \r
-  @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer\r
+  The function is always called in TPL_NOTIFY.\r
 \r
 \r
-  @retval EFI_NOT_READY  Input from console not ready yet.\r
-  @retval EFI_SUCCESS    Function executed successfully.\r
+  @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
+VOID\r
 KeyGetchar (\r
   IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
   )\r
 {\r
 KeyGetchar (\r
   IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT8       ScanCode;\r
-  UINT8       Readed;\r
-  BOOLEAN     Extended;\r
-  UINT8       ScancodeArr[4];\r
-  UINTN       Index;\r
+  EFI_STATUS                     Status;\r
+  UINT8                          ScanCode;\r
+  BOOLEAN                        Extended;\r
+  UINTN                          Index;\r
+  EFI_KEY_DATA                   KeyData;\r
+  LIST_ENTRY                     *Link;\r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;\r
   //\r
   // 4 bytes most\r
   //\r
   //\r
   // 4 bytes most\r
   //\r
-  UINT32      ScancodeArrPos;\r
+  UINT8                          ScancodeArr[4];\r
+  UINT32                         ScancodeArrPos;\r
   //\r
   // point to the current position in ScancodeArr\r
   //\r
 \r
   //\r
   // point to the current position in ScancodeArr\r
   //\r
 \r
-  Readed          = 0;\r
   Extended        = FALSE;\r
   ScancodeArrPos  = 0;\r
   Extended        = FALSE;\r
   ScancodeArrPos  = 0;\r
-\r
-  //\r
-  // Read one byte of the scan code and store it into the memory buffer\r
-  // This block of code is added to insert an action that is equivalent to\r
-  // the timer event handling function, so as to increase the frequency of\r
-  // detecting the availability of keys. Timer event has a max frequency of\r
-  // 18Hz which is insufficient\r
-  //\r
-  //\r
-  // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that\r
-  // KB is not connected to system. If KB is not connected to system, driver will find there's  something\r
-  // error in the following code and wait for the input buffer empty, this waiting time shoulb be  short enough since\r
-  // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
-  // Just skip the 'resend' process simply.\r
-  //\r
-\r
-\r
-  if (((KeyReadStatusRegister (ConsoleIn) & 0x21) == 0x1) && (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT)) {\r
-\r
-    Readed = KeyReadDataRegister (ConsoleIn);\r
-    //\r
-    // put the scancode into the memory scancode buffer\r
-    //\r
-    ConsoleIn->ScancodeBufCount++;\r
-    ConsoleIn->ScancodeBufEndPos++;\r
-    if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
-      ConsoleIn->ScancodeBufEndPos = 0;\r
-    }\r
-\r
-    ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Readed;\r
-\r
-    //\r
-    // Handle Alt+Ctrl+Del Key combination\r
-    //\r
-    switch (Readed) {\r
-\r
-    case SCANCODE_CTRL_MAKE:\r
-      ConsoleIn->Ctrled = TRUE;\r
-      break;\r
-\r
-    case SCANCODE_CTRL_BREAK:\r
-      ConsoleIn->Ctrled = FALSE;\r
-      break;\r
-\r
-    case SCANCODE_ALT_MAKE:\r
-      ConsoleIn->Alted = TRUE;\r
-      break;\r
-\r
-    case SCANCODE_ALT_BREAK:\r
-      ConsoleIn->Alted = FALSE;\r
-      break;\r
-    }\r
-    //\r
-    // if Alt+Ctrl+Del, Reboot the System\r
-    //\r
-    if (ConsoleIn->Ctrled && ConsoleIn->Alted && Readed == 0x53) {\r
-      gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
-    }\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
 \r
   //\r
   // Check if there are enough bytes of scancode representing a single key\r
   // available in the buffer\r
   //\r
   while (TRUE) {\r
 \r
-    Status          = GetScancodeBufHead (ConsoleIn, 1, ScancodeArr);\r
-    ScancodeArrPos  = 0;\r
+    Status            = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 1, ScancodeArr);\r
+    ScancodeArrPos    = 0;\r
     if (EFI_ERROR (Status)) {\r
     if (EFI_ERROR (Status)) {\r
-      return EFI_NOT_READY;\r
+      return ;\r
     }\r
 \r
     if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {\r
       Extended        = TRUE;\r
     }\r
 \r
     if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {\r
       Extended        = TRUE;\r
-      Status          = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);\r
+      Status          = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 2, ScancodeArr);\r
       ScancodeArrPos  = 1;\r
       if (EFI_ERROR (Status)) {\r
       ScancodeArrPos  = 1;\r
       if (EFI_ERROR (Status)) {\r
-        return EFI_NOT_READY;\r
+        return ;\r
       }\r
     }\r
     //\r
       }\r
     }\r
     //\r
@@ -1322,29 +1196,29 @@ KeyGetchar (
     //\r
     if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {\r
 \r
     //\r
     if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {\r
 \r
-      Status          = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);\r
+      Status          = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 2, ScancodeArr);\r
       ScancodeArrPos  = 1;\r
 \r
       if (EFI_ERROR (Status)) {\r
       ScancodeArrPos  = 1;\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return EFI_NOT_READY;\r
+        return ;\r
       }\r
 \r
       }\r
 \r
-      Status          = GetScancodeBufHead (ConsoleIn, 3, ScancodeArr);\r
+      Status          = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 3, ScancodeArr);\r
       ScancodeArrPos  = 2;\r
 \r
       if (EFI_ERROR (Status)) {\r
       ScancodeArrPos  = 2;\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return EFI_NOT_READY;\r
+        return ;\r
       }\r
 \r
       }\r
 \r
-      PopScancodeBufHead (ConsoleIn, 3, ScancodeArr);\r
-      return EFI_NOT_READY;\r
+      PopScancodeBufHead (&ConsoleIn->ScancodeQueue, 3, ScancodeArr);\r
+      return ;\r
     }\r
     //\r
     // if we reach this position, scancodes for a key is in buffer now,pop them\r
     //\r
     }\r
     //\r
     // if we reach this position, scancodes for a key is in buffer now,pop them\r
     //\r
-    Status = PopScancodeBufHead (ConsoleIn, ScancodeArrPos + 1, ScancodeArr);\r
+    Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);\r
     if (EFI_ERROR (Status)) {\r
     if (EFI_ERROR (Status)) {\r
-      return EFI_NOT_READY;\r
+      return ;\r
     }\r
     //\r
     // store the last available byte, this byte of scancode will be checked\r
     }\r
     //\r
     // store the last available byte, this byte of scancode will be checked\r
@@ -1446,55 +1320,56 @@ KeyGetchar (
       break;\r
     }\r
   }\r
       break;\r
     }\r
   }\r
+\r
   //\r
   //\r
-  // Treat Numeric Key Pad "/" specially\r
+  // Handle Ctrl+Alt+Del hotkey\r
   //\r
   //\r
-  if (Extended && ScanCode == 0x35) {\r
-    ConsoleIn->Key.ScanCode     = SCAN_NULL;\r
-    ConsoleIn->Key.UnicodeChar  = L'/';\r
-    return EFI_SUCCESS;\r
+  if (ConsoleIn->Alt && ConsoleIn->Ctrl && ScanCode == SCANCODE_DELETE_MAKE) {\r
+    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
   }\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
   //\r
   //\r
-  // Convert Keyboard ScanCode into an EFI Key\r
+  // Treat Numeric Key Pad "/" specially\r
   //\r
   //\r
-  for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {\r
-    if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {\r
-      ConsoleIn->Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;\r
-      if (ConsoleIn->Shift) {\r
-        ConsoleIn->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
-        if (ConsoleIn->Key.UnicodeChar >= L'A' && ConsoleIn->Key.UnicodeChar <= L'Z') {\r
+  if (Extended && ScanCode == 0x35) {\r
+    KeyData.Key.UnicodeChar = L'/';\r
+    KeyData.Key.ScanCode    = SCAN_NULL;\r
+  } else {\r
+    //\r
+    // Convert Keyboard ScanCode into an EFI Key\r
+    //\r
+    for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {\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
+            (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
         }\r
           ConsoleIn->LeftShift  = FALSE;\r
           ConsoleIn->RightShift = FALSE;\r
         }\r
-      } else {\r
-        ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\r
-      }\r
-      //\r
-      // alphabetic key is affected by CapsLock State\r
-      //\r
-      if (ConsoleIn->CapsLock) {\r
-        if (ConsoleIn->Key.UnicodeChar >= L'a' && ConsoleIn->Key.UnicodeChar <= L'z') {\r
-          ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;\r
-        } else if (ConsoleIn->Key.UnicodeChar >= L'A' && ConsoleIn->Key.UnicodeChar <= L'Z') {\r
-          ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\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->Ctrled) {\r
-        if (ConsoleIn->Key.UnicodeChar >= L'a' && ConsoleIn->Key.UnicodeChar <= L'z') {\r
-          ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - L'a' + 1);\r
-        } else if (ConsoleIn->Key.UnicodeChar >= L'A' && ConsoleIn->Key.UnicodeChar <= L'Z') {\r
-          ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - L'A' + 1);\r
+        //\r
+        // alphabetic key is affected by CapsLock State\r
+        //\r
+        if (ConsoleIn->CapsLock) {\r
+          if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
+            KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A');\r
+          } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
+            KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a');\r
+          }\r
         }\r
         }\r
+        break;\r
       }\r
       }\r
-\r
-      break;\r
     }\r
   }\r
 \r
     }\r
   }\r
 \r
@@ -1502,58 +1377,83 @@ KeyGetchar (
   // distinguish numeric key pad keys' 'up symbol' and 'down symbol'\r
   //\r
   if (ScanCode >= 0x47 && ScanCode <= 0x53) {\r
   // distinguish numeric key pad keys' 'up symbol' and 'down symbol'\r
   //\r
   if (ScanCode >= 0x47 && ScanCode <= 0x53) {\r
-\r
     if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {\r
     if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {\r
-      ConsoleIn->Key.ScanCode = SCAN_NULL;\r
+      KeyData.Key.ScanCode = SCAN_NULL;\r
     } else if (ScanCode != 0x4a && ScanCode != 0x4e) {\r
     } else if (ScanCode != 0x4a && ScanCode != 0x4e) {\r
-      ConsoleIn->Key.UnicodeChar = 0x0000;\r
+      KeyData.Key.UnicodeChar = CHAR_NULL;\r
     }\r
   }\r
   //\r
   // If the key can not be converted then just return.\r
   //\r
     }\r
   }\r
   //\r
   // If the key can not be converted then just return.\r
   //\r
-  if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x0000) {\r
-    return EFI_NOT_READY;\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
   }\r
 \r
   //\r
   // Save the Shift/Toggle state\r
   //\r
   if (ConsoleIn->Ctrl) {\r
-    ConsoleIn->KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;\r
   }                                    \r
   if (ConsoleIn->Alt) {                \r
   }                                    \r
   if (ConsoleIn->Alt) {                \r
-    ConsoleIn->KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;\r
   }                                    \r
   if (ConsoleIn->LeftShift) {          \r
   }                                    \r
   if (ConsoleIn->LeftShift) {          \r
-    ConsoleIn->KeyState.KeyShiftState  |= EFI_LEFT_SHIFT_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= EFI_LEFT_SHIFT_PRESSED;\r
   }                                    \r
   if (ConsoleIn->RightShift) {         \r
   }                                    \r
   if (ConsoleIn->RightShift) {         \r
-    ConsoleIn->KeyState.KeyShiftState  |= EFI_RIGHT_SHIFT_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= EFI_RIGHT_SHIFT_PRESSED;\r
   }                                    \r
   if (ConsoleIn->LeftLogo) {           \r
   }                                    \r
   if (ConsoleIn->LeftLogo) {           \r
-    ConsoleIn->KeyState.KeyShiftState  |= EFI_LEFT_LOGO_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= EFI_LEFT_LOGO_PRESSED;\r
   }                                    \r
   if (ConsoleIn->RightLogo) {          \r
   }                                    \r
   if (ConsoleIn->RightLogo) {          \r
-    ConsoleIn->KeyState.KeyShiftState  |= EFI_RIGHT_LOGO_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= EFI_RIGHT_LOGO_PRESSED;\r
   }                                    \r
   if (ConsoleIn->Menu) {               \r
   }                                    \r
   if (ConsoleIn->Menu) {               \r
-    ConsoleIn->KeyState.KeyShiftState  |= EFI_MENU_KEY_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= EFI_MENU_KEY_PRESSED;\r
   }                                    \r
   if (ConsoleIn->SysReq) {             \r
   }                                    \r
   if (ConsoleIn->SysReq) {             \r
-    ConsoleIn->KeyState.KeyShiftState  |= EFI_SYS_REQ_PRESSED;\r
+    KeyData.KeyState.KeyShiftState  |= EFI_SYS_REQ_PRESSED;\r
   }  \r
   if (ConsoleIn->CapsLock) {\r
   }  \r
   if (ConsoleIn->CapsLock) {\r
-    ConsoleIn->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
+    KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
   }\r
   if (ConsoleIn->NumLock) {\r
   }\r
   if (ConsoleIn->NumLock) {\r
-    ConsoleIn->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
+    KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
   }\r
   if (ConsoleIn->ScrollLock) {\r
   }\r
   if (ConsoleIn->ScrollLock) {\r
-    ConsoleIn->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
+    KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
   }\r
 \r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  //\r
+  // Invoke notification functions if exist\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
+                      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
+    }\r
+  }\r
+\r
+  PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -1737,11 +1637,10 @@ InitKeyboard (
   //\r
   // Clear Memory Scancode Buffer\r
   //\r
   //\r
   // Clear Memory Scancode Buffer\r
   //\r
-  ConsoleIn->ScancodeBufStartPos  = 0;\r
-  ConsoleIn->ScancodeBufEndPos    = KEYBOARD_BUFFER_MAX_COUNT - 1;\r
-  ConsoleIn->ScancodeBufCount     = 0;\r
-  ConsoleIn->Ctrled               = FALSE;\r
-  ConsoleIn->Alted                = FALSE;\r
+  ConsoleIn->ScancodeQueue.Head = 0;\r
+  ConsoleIn->ScancodeQueue.Tail = 0;\r
+  ConsoleIn->EfiKeyQueue.Head   = 0;\r
+  ConsoleIn->EfiKeyQueue.Tail   = 0;\r
 \r
   //\r
   // Reset the status indicators\r
 \r
   //\r
   // Reset the status indicators\r