]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / TerminalConIn.c
index b82ff3d8afcf76e0563c71cb78975ac1330de3cd..4ede41677493da9c72af5a37ac8cb175cb3b4567 100644 (file)
@@ -1,14 +1,10 @@
 /** @file\r
   Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -17,7 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 /**\r
   Reads the next keystroke from the input device. The WaitForKey Event can\r
-  be used to test for existance of a keystroke via WaitForEvent () call.\r
+  be used to test for existence of a keystroke via WaitForEvent () call.\r
 \r
   @param  TerminalDevice           Terminal driver private structure\r
   @param  KeyData                  A pointer to a buffer that is filled in with the\r
@@ -25,9 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
                                    pressed.\r
 \r
   @retval EFI_SUCCESS              The keystroke information was returned.\r
-  @retval EFI_NOT_READY            There was no keystroke data availiable.\r
-  @retval EFI_DEVICE_ERROR         The keystroke information was not returned due\r
-                                   to hardware errors.\r
+  @retval EFI_NOT_READY            There was no keystroke data available.\r
   @retval EFI_INVALID_PARAMETER    KeyData is NULL.\r
 \r
 **/\r
@@ -37,45 +31,15 @@ ReadKeyStrokeWorker (
   OUT EFI_KEY_DATA *KeyData\r
   )\r
 {\r
-  EFI_STATUS                      Status;\r
-  LIST_ENTRY                      *Link;\r
-  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;\r
-\r
   if (KeyData == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  //\r
-  // Initialize *Key to nonsense value.\r
-  //\r
-  KeyData->Key.ScanCode    = SCAN_NULL;\r
-  KeyData->Key.UnicodeChar = 0;\r
-\r
-  Status = TerminalConInCheckForKey (&TerminalDevice->SimpleInput);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_NOT_READY;\r
-  }\r
-\r
-  if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {\r
-    return EFI_NOT_READY;\r
-  }\r
-\r
   KeyData->KeyState.KeyShiftState  = 0;\r
   KeyData->KeyState.KeyToggleState = 0;\r
 \r
-  //\r
-  // Invoke notification functions if exist\r
-  //\r
-  for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
-    CurrentNotify = CR (\r
-                      Link,\r
-                      TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
-                      NotifyEntry,\r
-                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
-                      );\r
-    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
-      CurrentNotify->KeyNotificationFn (KeyData);\r
-    }\r
+  if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {\r
+    return EFI_NOT_READY;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -90,8 +54,8 @@ ReadKeyStrokeWorker (
   @param  This                     Indicates the calling context.\r
   @param  ExtendedVerification     Skip by this driver.\r
 \r
-  @return EFI_SUCCESS              The reset operation succeeds.\r
-  @return EFI_DEVICE_ERROR         The dependent serial port reset fails.\r
+  @retval EFI_SUCCESS              The reset operation succeeds.\r
+  @retval EFI_DEVICE_ERROR         The dependent serial port reset fails.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -111,23 +75,24 @@ TerminalConInReset (
   //\r
   REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
     EFI_PROGRESS_CODE,\r
-    PcdGet32 (PcdStatusCodeValueRemoteConsoleReset),\r
+    (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),\r
     TerminalDevice->DevicePath\r
     );\r
 \r
   Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);\r
 \r
   //\r
-  // clear all the internal buffer for keys\r
+  // Make all the internal buffer empty for keys\r
   //\r
-  InitializeRawFiFo (TerminalDevice);\r
-  InitializeUnicodeFiFo (TerminalDevice);\r
-  InitializeEfiKeyFiFo (TerminalDevice);\r
+  TerminalDevice->RawFiFo->Head     = TerminalDevice->RawFiFo->Tail;\r
+  TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail;\r
+  TerminalDevice->EfiKeyFiFo->Head  = TerminalDevice->EfiKeyFiFo->Tail;\r
+  TerminalDevice->EfiKeyFiFoForNotify->Head = TerminalDevice->EfiKeyFiFoForNotify->Tail;\r
 \r
   if (EFI_ERROR (Status)) {\r
     REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
       EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-      PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
+      (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\r
       TerminalDevice->DevicePath\r
       );\r
   }\r
@@ -143,9 +108,9 @@ TerminalConInReset (
                               keystroke information for the key that was sent\r
                               from terminal.\r
 \r
-  @return EFI_SUCCESS         The keystroke information is returned successfully.\r
-  @return EFI_NOT_READY       There is no keystroke data available.\r
-  @return EFI_DEVICE_ERROR    The dependent serial device encounters error.\r
+  @retval EFI_SUCCESS         The keystroke information is returned successfully.\r
+  @retval EFI_NOT_READY       There is no keystroke data available.\r
+  @retval EFI_DEVICE_ERROR    The dependent serial device encounters error.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -178,6 +143,8 @@ TerminalConInReadKeyStroke (
 /**\r
   Check if the key already has been registered.\r
 \r
+  If both RegsiteredData and InputData is NULL, then ASSERT().\r
+\r
   @param  RegsiteredData           A pointer to a buffer that is filled in with the\r
                                    keystroke state data for the key that was\r
                                    registered.\r
@@ -186,7 +153,7 @@ TerminalConInReadKeyStroke (
                                    pressed.\r
 \r
   @retval TRUE                     Key be pressed matches a registered key.\r
-  @retval FLASE                    Match failed.\r
+  @retval FALSE                    Match failed.\r
 \r
 **/\r
 BOOLEAN\r
@@ -214,8 +181,6 @@ IsKeyRegistered (
   @param  Event                    Indicates the event that invoke this function.\r
   @param  Context                  Indicates the calling context.\r
 \r
-  @return none.\r
-\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -224,12 +189,7 @@ TerminalConInWaitForKeyEx (
   IN  VOID            *Context\r
   )\r
 {\r
-  TERMINAL_DEV            *TerminalDevice;\r
-\r
-  TerminalDevice  = TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context);\r
-\r
-  TerminalConInWaitForKey (Event, &TerminalDevice->SimpleInput);\r
-\r
+  TerminalConInWaitForKey (Event, Context);\r
 }\r
 \r
 //\r
@@ -237,7 +197,7 @@ TerminalConInWaitForKeyEx (
 //\r
 \r
 /**\r
-  Reset the input device and optionaly run diagnostics\r
+  Reset the input device and optionally run diagnostics\r
 \r
   @param  This                     Protocol instance pointer.\r
   @param  ExtendedVerification     Driver may perform diagnostics on reset.\r
@@ -271,7 +231,7 @@ TerminalConInResetEx (
 \r
 /**\r
   Reads the next keystroke from the input device. The WaitForKey Event can\r
-  be used to test for existance of a keystroke via WaitForEvent () call.\r
+  be used to test for existence of a keystroke via WaitForEvent () call.\r
 \r
   @param  This                     Protocol instance pointer.\r
   @param  KeyData                  A pointer to a buffer that is filled in with the\r
@@ -279,7 +239,7 @@ TerminalConInResetEx (
                                    pressed.\r
 \r
   @retval EFI_SUCCESS              The keystroke information was returned.\r
-  @retval EFI_NOT_READY            There was no keystroke data availiable.\r
+  @retval EFI_NOT_READY            There was no keystroke data available.\r
   @retval EFI_DEVICE_ERROR         The keystroke information was not returned due\r
                                    to hardware errors.\r
   @retval EFI_INVALID_PARAMETER    KeyData is NULL.\r
@@ -331,6 +291,10 @@ TerminalConInSetState (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -339,17 +303,20 @@ TerminalConInSetState (
   Register a notification function for a particular keystroke for the input device.\r
 \r
   @param  This                     Protocol instance pointer.\r
-  @param  KeyData                  A pointer to a buffer that is filled in with the\r
-                                   keystroke information data for the key that was\r
-                                   pressed.\r
+  @param  KeyData                  A pointer to a buffer that is filled in with\r
+                                   the keystroke information for the key that was\r
+                                   pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState\r
+                                   and KeyData.KeyState.KeyShiftState are 0, then any incomplete\r
+                                   keystroke will trigger a notification of the KeyNotificationFunction.\r
   @param  KeyNotificationFunction  Points to the function to be called when the key\r
-                                   sequence is typed specified by KeyData.\r
+                                   sequence is typed specified by KeyData. This notification function\r
+                                   should be called at <=TPL_CALLBACK.\r
   @param  NotifyHandle             Points to the unique handle assigned to the\r
                                    registered notification.\r
 \r
   @retval EFI_SUCCESS              The notification function was registered\r
                                    successfully.\r
-  @retval EFI_OUT_OF_RESOURCES     Unable to allocate resources for necesssary data\r
+  @retval EFI_OUT_OF_RESOURCES     Unable to allocate resources for necessary data\r
                                    structures.\r
   @retval EFI_INVALID_PARAMETER    KeyData or NotifyHandle is NULL.\r
 \r
@@ -360,13 +327,13 @@ TerminalConInRegisterKeyNotify (
   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
   TERMINAL_DEV                    *TerminalDevice;\r
   TERMINAL_CONSOLE_IN_EX_NOTIFY   *NewNotify;\r
   LIST_ENTRY                      *Link;\r
+  LIST_ENTRY                      *NotifyList;\r
   TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;\r
 \r
   if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
@@ -378,7 +345,8 @@ TerminalConInRegisterKeyNotify (
   //\r
   // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
   //\r
-  for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+  NotifyList = &TerminalDevice->NotifyList;\r
+  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
     CurrentNotify = CR (\r
                       Link,\r
                       TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
@@ -387,7 +355,7 @@ TerminalConInRegisterKeyNotify (
                       );\r
     if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
       if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
-        *NotifyHandle = CurrentNotify->NotifyHandle;\r
+        *NotifyHandle = CurrentNotify;\r
         return EFI_SUCCESS;\r
       }\r
     }\r
@@ -403,19 +371,10 @@ TerminalConInRegisterKeyNotify (
 \r
   NewNotify->Signature         = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
   NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
-  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
   InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);\r
-  //\r
-  // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
-  //\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &NewNotify->NotifyHandle,\r
-                  &gSimpleTextInExNotifyGuid,\r
-                  NULL,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-  *NotifyHandle                = NewNotify->NotifyHandle;\r
+\r
+  *NotifyHandle                = NewNotify;\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -431,74 +390,57 @@ TerminalConInRegisterKeyNotify (
   @retval EFI_SUCCESS              The notification function was unregistered\r
                                    successfully.\r
   @retval EFI_INVALID_PARAMETER    The NotificationHandle is invalid.\r
-  @retval EFI_NOT_FOUND            Can not find the matching entry in database.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 TerminalConInUnregisterKeyNotify (\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
   TERMINAL_DEV                    *TerminalDevice;\r
   LIST_ENTRY                      *Link;\r
   TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;\r
+  LIST_ENTRY                      *NotifyList;\r
 \r
   if (NotificationHandle == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Status = gBS->OpenProtocol (\r
-                  NotificationHandle,\r
-                  &gSimpleTextInExNotifyGuid,\r
-                  NULL,\r
-                  NULL,\r
-                  NULL,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
 \r
-  for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+  NotifyList = &TerminalDevice->NotifyList;\r
+  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
     CurrentNotify = CR (\r
                       Link,\r
                       TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
                       NotifyEntry,\r
                       TERMINAL_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
       RemoveEntryList (&CurrentNotify->NotifyEntry);\r
-      Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                      CurrentNotify->NotifyHandle,\r
-                      &gSimpleTextInExNotifyGuid,\r
-                      NULL,\r
-                      NULL\r
-                      );\r
-      ASSERT_EFI_ERROR (Status);\r
+\r
       gBS->FreePool (CurrentNotify);\r
       return EFI_SUCCESS;\r
     }\r
   }\r
 \r
-  return EFI_NOT_FOUND;\r
+  //\r
+  // Can not find the matching entry in database.\r
+  //\r
+  return EFI_INVALID_PARAMETER;\r
 }\r
 \r
 /**\r
-  Translate raw data into Unicode (according to different encode), and \r
-  translate Unicode into key information. (according to different standard). \r
+  Translate raw data into Unicode (according to different encode), and\r
+  translate Unicode into key information. (according to different standard).\r
 \r
   @param  TerminalDevice       Terminal driver private structure.\r
 \r
-  @return none.\r
-\r
 **/\r
 VOID\r
 TranslateRawDataToEfiKey (\r
@@ -507,14 +449,15 @@ TranslateRawDataToEfiKey (
 {\r
   switch (TerminalDevice->TerminalType) {\r
 \r
-  case PCANSITYPE:\r
-  case VT100TYPE:\r
-  case VT100PLUSTYPE:\r
+  case TerminalTypePcAnsi:\r
+  case TerminalTypeVt100:\r
+  case TerminalTypeVt100Plus:\r
+  case TerminalTypeTtyTerm:\r
     AnsiRawDataToUnicode (TerminalDevice);\r
     UnicodeToEfiKey (TerminalDevice);\r
     break;\r
 \r
-  case VTUTF8TYPE:\r
+  case TerminalTypeVtUtf8:\r
     //\r
     // Process all the raw data in the RawFIFO,\r
     // put the processed key into UnicodeFIFO.\r
@@ -538,8 +481,6 @@ TranslateRawDataToEfiKey (
   @param  Event                    Indicates the event that invoke this function.\r
   @param  Context                  Indicates the calling context.\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -552,28 +493,23 @@ TerminalConInWaitForKey (
   // Someone is waiting on the keystroke event, if there's\r
   // a key pending, signal the event\r
   //\r
-  // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
-  //\r
-  if (!EFI_ERROR (TerminalConInCheckForKey (Context))) {\r
+  if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) {\r
 \r
     gBS->SignalEvent (Event);\r
   }\r
 }\r
 \r
-\r
 /**\r
-  Check for a pending key in the Efi Key FIFO or Serial device buffer.\r
-\r
-  @param  This                     Indicates the calling context.\r
-\r
-  @retval EFI_SUCCESS              There is key pending.\r
-  @retval EFI_NOT_READY            There is no key pending.\r
-  @retval EFI_DEVICE_ERROR         If Serial IO is not attched to serial device.\r
+  Timer handler to poll the key from serial.\r
 \r
+  @param  Event                    Indicates the event that invoke this function.\r
+  @param  Context                  Indicates the calling context.\r
 **/\r
-EFI_STATUS\r
-TerminalConInCheckForKey (\r
-  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This\r
+VOID\r
+EFIAPI\r
+TerminalConInTimerHandler (\r
+  IN EFI_EVENT            Event,\r
+  IN VOID                 *Context\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -584,11 +520,11 @@ TerminalConInCheckForKey (
   EFI_SERIAL_IO_PROTOCOL  *SerialIo;\r
   UINTN                   SerialInTimeOut;\r
 \r
-  TerminalDevice  = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
+  TerminalDevice  = (TERMINAL_DEV *) Context;\r
 \r
   SerialIo        = TerminalDevice->SerialIo;\r
   if (SerialIo == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
+    return ;\r
   }\r
   //\r
   //  if current timeout value for serial device is not identical with\r
@@ -623,71 +559,104 @@ TerminalConInCheckForKey (
     }\r
   }\r
   //\r
-  //  Check whether serial buffer is empty.\r
+  // Check whether serial buffer is empty.\r
+  // Skip the key transfer loop only if the SerialIo protocol instance\r
+  // successfully reports EFI_SERIAL_INPUT_BUFFER_EMPTY.\r
   //\r
   Status = SerialIo->GetControl (SerialIo, &Control);\r
-\r
-  if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {\r
-    //\r
-    // Translate all the raw data in RawFIFO into EFI Key,\r
-    // according to different terminal type supported.\r
+  if (EFI_ERROR (Status) || ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) == 0)) {\r
     //\r
-    TranslateRawDataToEfiKey (TerminalDevice);\r
-\r
-    //\r
-    //  if there is pre-fetched Efi Key in EfiKeyFIFO buffer,\r
-    //  return directly.\r
+    // Fetch all the keys in the serial buffer,\r
+    // and insert the byte stream into RawFIFO.\r
     //\r
-    if (!IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
-      return EFI_SUCCESS;\r
-    } else {\r
-      return EFI_NOT_READY;\r
-    }\r
-  }\r
-  //\r
-  // Fetch all the keys in the serial buffer,\r
-  // and insert the byte stream into RawFIFO.\r
-  //\r
-  do {\r
+    while (!IsRawFiFoFull (TerminalDevice)) {\r
 \r
-    Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);\r
+      Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);\r
 \r
-    if (EFI_ERROR (Status)) {\r
-      if (Status == EFI_DEVICE_ERROR) {\r
-        REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-          EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-          PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError),\r
-          TerminalDevice->DevicePath\r
-          );\r
+      if (EFI_ERROR (Status)) {\r
+        if (Status == EFI_DEVICE_ERROR) {\r
+          REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+            EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+            (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR),\r
+            TerminalDevice->DevicePath\r
+            );\r
+        }\r
+        break;\r
       }\r
-      break;\r
-    }\r
 \r
-    RawFiFoInsertOneKey (TerminalDevice, Input);\r
-  } while (TRUE);\r
+      RawFiFoInsertOneKey (TerminalDevice, Input);\r
+    }\r
+  }\r
 \r
   //\r
   // Translate all the raw data in RawFIFO into EFI Key,\r
   // according to different terminal type supported.\r
   //\r
   TranslateRawDataToEfiKey (TerminalDevice);\r
+}\r
 \r
-  if (IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
-    return EFI_NOT_READY;\r
-  }\r
+/**\r
+  Process key notify.\r
 \r
-  return EFI_SUCCESS;\r
+  @param  Event                 Indicates the event that invoke this function.\r
+  @param  Context               Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+  IN  EFI_EVENT                 Event,\r
+  IN  VOID                      *Context\r
+  )\r
+{\r
+  BOOLEAN                       HasKey;\r
+  TERMINAL_DEV                  *TerminalDevice;\r
+  EFI_INPUT_KEY                 Key;\r
+  EFI_KEY_DATA                  KeyData;\r
+  LIST_ENTRY                    *Link;\r
+  LIST_ENTRY                    *NotifyList;\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+  EFI_TPL                       OldTpl;\r
+\r
+  TerminalDevice = (TERMINAL_DEV *) Context;\r
+\r
+  //\r
+  // Invoke notification functions.\r
+  //\r
+  NotifyList = &TerminalDevice->NotifyList;\r
+  while (TRUE) {\r
+    //\r
+    // Enter critical section\r
+    //\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    HasKey = EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice->EfiKeyFiFoForNotify, &Key);\r
+    CopyMem (&KeyData.Key, &Key, sizeof (EFI_INPUT_KEY));\r
+    KeyData.KeyState.KeyShiftState  = 0;\r
+    KeyData.KeyState.KeyToggleState = 0;\r
+    //\r
+    // Leave critical section\r
+    //\r
+    gBS->RestoreTPL (OldTpl);\r
+    if (!HasKey) {\r
+      break;\r
+    }\r
+    for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
+      CurrentNotify = CR (Link, TERMINAL_CONSOLE_IN_EX_NOTIFY, NotifyEntry, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+      if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+        CurrentNotify->KeyNotificationFn (&KeyData);\r
+      }\r
+    }\r
+  }\r
 }\r
 \r
 /**\r
   Get one key out of serial buffer.\r
 \r
-  @param  SerialIo           Serial I/O protocl attached to the serial device.\r
+  @param  SerialIo           Serial I/O protocol attached to the serial device.\r
   @param  Output             The fetched key.\r
 \r
-  @return EFI_NOT_READY      If serial buffer is empty.\r
-  @return EFI_DEVICE_ERROR   If reading serial buffer encounter error.\r
-  @return EFI_SUCCESS        If reading serial buffer successfully, put\r
+  @retval EFI_NOT_READY      If serial buffer is empty.\r
+  @retval EFI_DEVICE_ERROR   If reading serial buffer encounter error.\r
+  @retval EFI_SUCCESS        If reading serial buffer successfully, put\r
                              the fetched key to the parameter output.\r
 \r
 **/\r
@@ -731,8 +700,8 @@ GetOneKeyFromSerial (
   @param  TerminalDevice       Terminal driver private structure.\r
   @param  Input                The key will be input.\r
 \r
-  @return TRUE                 If insert successfully.\r
-  @return FLASE                If Raw Data buffer is full before key insertion,\r
+  @retval TRUE                 If insert successfully.\r
+  @retval FALSE                If Raw Data buffer is full before key insertion,\r
                                and the key is lost.\r
 \r
 **/\r
@@ -744,7 +713,7 @@ RawFiFoInsertOneKey (
 {\r
   UINT8 Tail;\r
 \r
-  Tail = TerminalDevice->RawFiFo.Tail;\r
+  Tail = TerminalDevice->RawFiFo->Tail;\r
 \r
   if (IsRawFiFoFull (TerminalDevice)) {\r
     //\r
@@ -753,9 +722,9 @@ RawFiFoInsertOneKey (
     return FALSE;\r
   }\r
 \r
-  TerminalDevice->RawFiFo.Data[Tail]  = Input;\r
+  TerminalDevice->RawFiFo->Data[Tail]  = Input;\r
 \r
-  TerminalDevice->RawFiFo.Tail        = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
+  TerminalDevice->RawFiFo->Tail        = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
 \r
   return TRUE;\r
 }\r
@@ -766,8 +735,8 @@ RawFiFoInsertOneKey (
   @param  TerminalDevice       Terminal driver private structure.\r
   @param  Output               The key will be removed.\r
 \r
-  @return TRUE                 If insert successfully.\r
-  @return FLASE                If Raw Data FIFO buffer is empty before remove operation.\r
+  @retval TRUE                 If insert successfully.\r
+  @retval FALSE                If Raw Data FIFO buffer is empty before remove operation.\r
 \r
 **/\r
 BOOLEAN\r
@@ -778,7 +747,7 @@ RawFiFoRemoveOneKey (
 {\r
   UINT8 Head;\r
 \r
-  Head = TerminalDevice->RawFiFo.Head;\r
+  Head = TerminalDevice->RawFiFo->Head;\r
 \r
   if (IsRawFiFoEmpty (TerminalDevice)) {\r
     //\r
@@ -788,9 +757,9 @@ RawFiFoRemoveOneKey (
     return FALSE;\r
   }\r
 \r
-  *Output                       = TerminalDevice->RawFiFo.Data[Head];\r
+  *Output                       = TerminalDevice->RawFiFo->Data[Head];\r
 \r
-  TerminalDevice->RawFiFo.Head  = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
+  TerminalDevice->RawFiFo->Head  = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
 \r
   return TRUE;\r
 }\r
@@ -800,8 +769,8 @@ RawFiFoRemoveOneKey (
 \r
   @param  TerminalDevice       Terminal driver private structure\r
 \r
-  @return TRUE                 If Raw Data FIFO buffer is empty.\r
-  @return FLASE                If Raw Data FIFO buffer is not empty.\r
+  @retval TRUE                 If Raw Data FIFO buffer is empty.\r
+  @retval FALSE                If Raw Data FIFO buffer is not empty.\r
 \r
 **/\r
 BOOLEAN\r
@@ -809,7 +778,7 @@ IsRawFiFoEmpty (
   TERMINAL_DEV  *TerminalDevice\r
   )\r
 {\r
-  if (TerminalDevice->RawFiFo.Head == TerminalDevice->RawFiFo.Tail) {\r
+  if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {\r
     return TRUE;\r
   } else {\r
     return FALSE;\r
@@ -821,8 +790,8 @@ IsRawFiFoEmpty (
 \r
   @param  TerminalDevice       Terminal driver private structure\r
 \r
-  @return TRUE                 If Raw Data FIFO buffer is full.\r
-  @return FLASE                If Raw Data FIFO buffer is not full.\r
+  @retval TRUE                 If Raw Data FIFO buffer is full.\r
+  @retval FALSE                If Raw Data FIFO buffer is not full.\r
 \r
 **/\r
 BOOLEAN\r
@@ -833,8 +802,8 @@ IsRawFiFoFull (
   UINT8 Tail;\r
   UINT8 Head;\r
 \r
-  Tail  = TerminalDevice->RawFiFo.Tail;\r
-  Head  = TerminalDevice->RawFiFo.Head;\r
+  Tail  = TerminalDevice->RawFiFo->Tail;\r
+  Head  = TerminalDevice->RawFiFo->Head;\r
 \r
   if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {\r
 \r
@@ -844,27 +813,177 @@ IsRawFiFoFull (
   return FALSE;\r
 }\r
 \r
+/**\r
+  Insert one pre-fetched key into the FIFO buffer.\r
+\r
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.\r
+  @param  Input                 The key will be input.\r
+\r
+  @retval TRUE                  If insert successfully.\r
+  @retval FALSE                 If FIFO buffer is full before key insertion,\r
+                                and the key is lost.\r
+\r
+**/\r
+BOOLEAN\r
+EfiKeyFiFoForNotifyInsertOneKey (\r
+  EFI_KEY_FIFO                  *EfiKeyFiFo,\r
+  EFI_INPUT_KEY                 *Input\r
+  )\r
+{\r
+  UINT8                         Tail;\r
+\r
+  Tail = EfiKeyFiFo->Tail;\r
+\r
+  if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo)) {\r
+    //\r
+    // FIFO is full\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  CopyMem (&EfiKeyFiFo->Data[Tail], Input, sizeof (EFI_INPUT_KEY));\r
+\r
+  EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Remove one pre-fetched key out of the FIFO buffer.\r
+\r
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.\r
+  @param  Output                The key will be removed.\r
+\r
+  @retval TRUE                  If remove successfully.\r
+  @retval FALSE                 If FIFO buffer is empty before remove operation.\r
+\r
+**/\r
+BOOLEAN\r
+EfiKeyFiFoForNotifyRemoveOneKey (\r
+  EFI_KEY_FIFO                  *EfiKeyFiFo,\r
+  EFI_INPUT_KEY                 *Output\r
+  )\r
+{\r
+  UINT8                         Head;\r
+\r
+  Head = EfiKeyFiFo->Head;\r
+  ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
+\r
+  if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo)) {\r
+    //\r
+    // FIFO is empty\r
+    //\r
+    Output->ScanCode    = SCAN_NULL;\r
+    Output->UnicodeChar = 0;\r
+    return FALSE;\r
+  }\r
+\r
+  CopyMem (Output, &EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));\r
+\r
+  EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Clarify whether FIFO buffer is empty.\r
+\r
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.\r
+\r
+  @retval TRUE                  If FIFO buffer is empty.\r
+  @retval FALSE                 If FIFO buffer is not empty.\r
+\r
+**/\r
+BOOLEAN\r
+IsEfiKeyFiFoForNotifyEmpty (\r
+  EFI_KEY_FIFO                  *EfiKeyFiFo\r
+  )\r
+{\r
+  if (EfiKeyFiFo->Head == EfiKeyFiFo->Tail) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Clarify whether FIFO buffer is full.\r
+\r
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.\r
+\r
+  @retval TRUE                  If FIFO buffer is full.\r
+  @retval FALSE                 If FIFO buffer is not full.\r
+\r
+**/\r
+BOOLEAN\r
+IsEfiKeyFiFoForNotifyFull (\r
+  EFI_KEY_FIFO                  *EfiKeyFiFo\r
+  )\r
+{\r
+  UINT8                         Tail;\r
+  UINT8                         Head;\r
+\r
+  Tail = EfiKeyFiFo->Tail;\r
+  Head = EfiKeyFiFo->Head;\r
+\r
+  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Insert one pre-fetched key into the FIFO buffer.\r
 \r
   @param  TerminalDevice       Terminal driver private structure.\r
   @param  Key                  The key will be input.\r
 \r
-  @return TRUE                 If insert successfully.\r
-  @return FLASE                If FIFO buffer is full before key insertion,\r
+  @retval TRUE                 If insert successfully.\r
+  @retval FALSE                If FIFO buffer is full before key insertion,\r
                                and the key is lost.\r
 \r
 **/\r
 BOOLEAN\r
 EfiKeyFiFoInsertOneKey (\r
-  TERMINAL_DEV      *TerminalDevice,\r
-  EFI_INPUT_KEY     Key\r
+  TERMINAL_DEV                    *TerminalDevice,\r
+  EFI_INPUT_KEY                   *Key\r
   )\r
 {\r
-  UINT8 Tail;\r
+  UINT8                           Tail;\r
+  LIST_ENTRY                      *Link;\r
+  LIST_ENTRY                      *NotifyList;\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;\r
+  EFI_KEY_DATA                    KeyData;\r
+\r
+  Tail = TerminalDevice->EfiKeyFiFo->Tail;\r
 \r
-  Tail = TerminalDevice->EfiKeyFiFo.Tail;\r
+  CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));\r
+  KeyData.KeyState.KeyShiftState  = 0;\r
+  KeyData.KeyState.KeyToggleState = 0;\r
 \r
+  //\r
+  // Signal KeyNotify process event if this key pressed matches any key registered.\r
+  //\r
+  NotifyList = &TerminalDevice->NotifyList;\r
+  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
+    CurrentNotify = CR (\r
+                      Link,\r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
+                      NotifyEntry,\r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\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
+      EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice->EfiKeyFiFoForNotify, Key);\r
+      gBS->SignalEvent (TerminalDevice->KeyNotifyProcessEvent);\r
+      break;\r
+    }\r
+  }\r
   if (IsEfiKeyFiFoFull (TerminalDevice)) {\r
     //\r
     // Efi Key FIFO is full\r
@@ -872,9 +991,9 @@ EfiKeyFiFoInsertOneKey (
     return FALSE;\r
   }\r
 \r
-  TerminalDevice->EfiKeyFiFo.Data[Tail] = Key;\r
+  CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));\r
 \r
-  TerminalDevice->EfiKeyFiFo.Tail       = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
+  TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
 \r
   return TRUE;\r
 }\r
@@ -885,8 +1004,8 @@ EfiKeyFiFoInsertOneKey (
   @param  TerminalDevice       Terminal driver private structure.\r
   @param  Output               The key will be removed.\r
 \r
-  @return TRUE                 If insert successfully.\r
-  @return FLASE                If FIFO buffer is empty before remove operation.\r
+  @retval TRUE                 If insert successfully.\r
+  @retval FALSE                If FIFO buffer is empty before remove operation.\r
 \r
 **/\r
 BOOLEAN\r
@@ -897,7 +1016,8 @@ EfiKeyFiFoRemoveOneKey (
 {\r
   UINT8 Head;\r
 \r
-  Head = TerminalDevice->EfiKeyFiFo.Head;\r
+  Head = TerminalDevice->EfiKeyFiFo->Head;\r
+  ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
 \r
   if (IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
     //\r
@@ -908,9 +1028,9 @@ EfiKeyFiFoRemoveOneKey (
     return FALSE;\r
   }\r
 \r
-  *Output                         = TerminalDevice->EfiKeyFiFo.Data[Head];\r
+  CopyMem (Output, &TerminalDevice->EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));\r
 \r
-  TerminalDevice->EfiKeyFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
+  TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
 \r
   return TRUE;\r
 }\r
@@ -920,8 +1040,8 @@ EfiKeyFiFoRemoveOneKey (
 \r
   @param  TerminalDevice       Terminal driver private structure\r
 \r
-  @return TRUE                 If FIFO buffer is empty.\r
-  @return FLASE                If FIFO buffer is not empty.\r
+  @retval TRUE                 If FIFO buffer is empty.\r
+  @retval FALSE                If FIFO buffer is not empty.\r
 \r
 **/\r
 BOOLEAN\r
@@ -929,7 +1049,7 @@ IsEfiKeyFiFoEmpty (
   TERMINAL_DEV  *TerminalDevice\r
   )\r
 {\r
-  if (TerminalDevice->EfiKeyFiFo.Head == TerminalDevice->EfiKeyFiFo.Tail) {\r
+  if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {\r
     return TRUE;\r
   } else {\r
     return FALSE;\r
@@ -941,8 +1061,8 @@ IsEfiKeyFiFoEmpty (
 \r
   @param  TerminalDevice       Terminal driver private structure\r
 \r
-  @return TRUE                 If FIFO buffer is full.\r
-  @return FLASE                If FIFO buffer is not full.\r
+  @retval TRUE                 If FIFO buffer is full.\r
+  @retval FALSE                If FIFO buffer is not full.\r
 \r
 **/\r
 BOOLEAN\r
@@ -953,8 +1073,8 @@ IsEfiKeyFiFoFull (
   UINT8 Tail;\r
   UINT8 Head;\r
 \r
-  Tail  = TerminalDevice->EfiKeyFiFo.Tail;\r
-  Head  = TerminalDevice->EfiKeyFiFo.Head;\r
+  Tail  = TerminalDevice->EfiKeyFiFo->Tail;\r
+  Head  = TerminalDevice->EfiKeyFiFo->Head;\r
 \r
   if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
 \r
@@ -970,8 +1090,8 @@ IsEfiKeyFiFoFull (
   @param  TerminalDevice       Terminal driver private structure.\r
   @param  Input                The key will be input.\r
 \r
-  @return TRUE                 If insert successfully.\r
-  @return FLASE                If Unicode FIFO buffer is full before key insertion,\r
+  @retval TRUE                 If insert successfully.\r
+  @retval FALSE                If Unicode FIFO buffer is full before key insertion,\r
                                and the key is lost.\r
 \r
 **/\r
@@ -983,7 +1103,9 @@ UnicodeFiFoInsertOneKey (
 {\r
   UINT8 Tail;\r
 \r
-  Tail = TerminalDevice->UnicodeFiFo.Tail;\r
+  Tail = TerminalDevice->UnicodeFiFo->Tail;\r
+  ASSERT (Tail < FIFO_MAX_NUMBER + 1);\r
+\r
 \r
   if (IsUnicodeFiFoFull (TerminalDevice)) {\r
     //\r
@@ -992,24 +1114,23 @@ UnicodeFiFoInsertOneKey (
     return FALSE;\r
   }\r
 \r
-  TerminalDevice->UnicodeFiFo.Data[Tail]  = Input;\r
+  TerminalDevice->UnicodeFiFo->Data[Tail]  = Input;\r
 \r
-  TerminalDevice->UnicodeFiFo.Tail        = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
+  TerminalDevice->UnicodeFiFo->Tail        = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
 \r
   return TRUE;\r
 }\r
 \r
 /**\r
   Remove one pre-fetched key out of the Unicode FIFO buffer.\r
+  The caller should guarantee that Unicode FIFO buffer is not empty\r
+  by IsUnicodeFiFoEmpty ().\r
 \r
   @param  TerminalDevice       Terminal driver private structure.\r
   @param  Output               The key will be removed.\r
 \r
-  @return TRUE                 If insert successfully.\r
-  @return FLASE                If Unicode FIFO buffer is empty before remove operation.\r
-\r
 **/\r
-BOOLEAN\r
+VOID\r
 UnicodeFiFoRemoveOneKey (\r
   TERMINAL_DEV  *TerminalDevice,\r
   UINT16        *Output\r
@@ -1017,21 +1138,12 @@ UnicodeFiFoRemoveOneKey (
 {\r
   UINT8 Head;\r
 \r
-  Head = TerminalDevice->UnicodeFiFo.Head;\r
-\r
-  if (IsUnicodeFiFoEmpty (TerminalDevice)) {\r
-    //\r
-    //  FIFO is empty\r
-    //\r
-    Output = NULL;\r
-    return FALSE;\r
-  }\r
-\r
-  *Output = TerminalDevice->UnicodeFiFo.Data[Head];\r
+  Head = TerminalDevice->UnicodeFiFo->Head;\r
+  ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
 \r
-  TerminalDevice->UnicodeFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
+  *Output = TerminalDevice->UnicodeFiFo->Data[Head];\r
 \r
-  return TRUE;\r
+  TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
 }\r
 \r
 /**\r
@@ -1039,8 +1151,8 @@ UnicodeFiFoRemoveOneKey (
 \r
   @param  TerminalDevice       Terminal driver private structure\r
 \r
-  @return TRUE                 If Unicode FIFO buffer is empty.\r
-  @return FLASE                If Unicode FIFO buffer is not empty.\r
+  @retval TRUE                 If Unicode FIFO buffer is empty.\r
+  @retval FALSE                If Unicode FIFO buffer is not empty.\r
 \r
 **/\r
 BOOLEAN\r
@@ -1048,7 +1160,7 @@ IsUnicodeFiFoEmpty (
   TERMINAL_DEV  *TerminalDevice\r
   )\r
 {\r
-  if (TerminalDevice->UnicodeFiFo.Head == TerminalDevice->UnicodeFiFo.Tail) {\r
+  if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {\r
     return TRUE;\r
   } else {\r
     return FALSE;\r
@@ -1060,8 +1172,8 @@ IsUnicodeFiFoEmpty (
 \r
   @param  TerminalDevice       Terminal driver private structure\r
 \r
-  @return TRUE                 If Unicode FIFO buffer is full.\r
-  @return FLASE                If Unicode FIFO buffer is not full.\r
+  @retval TRUE                 If Unicode FIFO buffer is full.\r
+  @retval FALSE                If Unicode FIFO buffer is not full.\r
 \r
 **/\r
 BOOLEAN\r
@@ -1072,8 +1184,8 @@ IsUnicodeFiFoFull (
   UINT8 Tail;\r
   UINT8 Head;\r
 \r
-  Tail  = TerminalDevice->UnicodeFiFo.Tail;\r
-  Head  = TerminalDevice->UnicodeFiFo.Head;\r
+  Tail  = TerminalDevice->UnicodeFiFo->Tail;\r
+  Head  = TerminalDevice->UnicodeFiFo->Head;\r
 \r
   if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
 \r
@@ -1083,38 +1195,11 @@ IsUnicodeFiFoFull (
   return FALSE;\r
 }\r
 \r
-/**\r
-  Count Unicode FIFO buffer.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure\r
-\r
-  @return The count in bytes of Unicode FIFO.\r
-\r
-**/\r
-UINT8\r
-UnicodeFiFoGetKeyCount (\r
-  TERMINAL_DEV    *TerminalDevice\r
-  )\r
-{\r
-  UINT8 Tail;\r
-  UINT8 Head;\r
-\r
-  Tail  = TerminalDevice->UnicodeFiFo.Tail;\r
-  Head  = TerminalDevice->UnicodeFiFo.Head;\r
-\r
-  if (Tail >= Head) {\r
-    return (UINT8) (Tail - Head);\r
-  } else {\r
-    return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);\r
-  }\r
-}\r
 \r
 /**\r
   Update the Unicode characters from a terminal input device into EFI Keys FIFO.\r
-  \r
-  @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys\r
 \r
-  @return None.\r
+  @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys\r
 \r
 **/\r
 VOID\r
@@ -1123,35 +1208,42 @@ UnicodeToEfiKeyFlushState (
   )\r
 {\r
   EFI_INPUT_KEY Key;\r
+  UINT32        InputState;\r
 \r
-  if ((TerminalDevice->InputState & INPUT_STATE_ESC) != 0) {\r
+  InputState = TerminalDevice->InputState;\r
+\r
+  if (IsEfiKeyFiFoFull (TerminalDevice)) {\r
+    return;\r
+  }\r
+\r
+  if ((InputState & INPUT_STATE_ESC) != 0) {\r
     Key.ScanCode    = SCAN_ESC;\r
     Key.UnicodeChar = 0;\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
   }\r
 \r
-  if ((TerminalDevice->InputState & INPUT_STATE_CSI) != 0) {\r
+  if ((InputState & INPUT_STATE_CSI) != 0) {\r
     Key.ScanCode    = SCAN_NULL;\r
     Key.UnicodeChar = CSI;\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
   }\r
 \r
-  if ((TerminalDevice->InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {\r
+  if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {\r
     Key.ScanCode    = SCAN_NULL;\r
     Key.UnicodeChar = LEFTOPENBRACKET;\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
   }\r
 \r
-  if ((TerminalDevice->InputState & INPUT_STATE_O) != 0) {\r
+  if ((InputState & INPUT_STATE_O) != 0) {\r
     Key.ScanCode    = SCAN_NULL;\r
     Key.UnicodeChar = 'O';\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
   }\r
 \r
-  if ((TerminalDevice->InputState & INPUT_STATE_2) != 0) {\r
+  if ((InputState & INPUT_STATE_2) != 0) {\r
     Key.ScanCode    = SCAN_NULL;\r
     Key.UnicodeChar = '2';\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
   }\r
 \r
   //\r
@@ -1169,11 +1261,11 @@ UnicodeToEfiKeyFlushState (
 \r
 /**\r
   Converts a stream of Unicode characters from a terminal input device into EFI Keys that\r
-  can be read through the Simple Input Protocol. \r
-  \r
+  can be read through the Simple Input Protocol.\r
+\r
   The table below shows the keyboard input mappings that this function supports.\r
   If the ESC sequence listed in one of the columns is presented, then it is translated\r
-  into the coorespoding EFI Scan Code.  If a matching sequence is not found, then the raw\r
+  into the corresponding EFI Scan Code.  If a matching sequence is not found, then the raw\r
   key strokes are converted into EFI Keys.\r
 \r
   2 seconds are allowed for an ESC sequence to be completed.  If the ESC sequence is not\r
@@ -1182,6 +1274,10 @@ UnicodeToEfiKeyFlushState (
   There is one special input sequence that will force the system to reset.\r
   This is ESC R ESC r ESC R.\r
 \r
+  Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.\r
+        The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /\r
+        DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.\r
+\r
   Symbols used in table below\r
   ===========================\r
     ESC = 0x1B\r
@@ -1229,8 +1325,6 @@ UnicodeToEfiKeyFlushState (
 \r
   @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 UnicodeToEfiKey (\r
@@ -1250,11 +1344,11 @@ UnicodeToEfiKey (
     TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
   }\r
 \r
-  while (!IsUnicodeFiFoEmpty(TerminalDevice)) {\r
+  while (!IsUnicodeFiFoEmpty (TerminalDevice) && !IsEfiKeyFiFoFull (TerminalDevice)) {\r
 \r
     if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
       //\r
-      // Check to see if the 2 second timer has expired\r
+      // Check to see if the 2 seconds timer has expired\r
       //\r
       TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
       if (!EFI_ERROR (TimerStatus)) {\r
@@ -1283,7 +1377,8 @@ UnicodeToEfiKey (
         continue;\r
       }\r
 \r
-      if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {\r
+      if (UnicodeChar == 'O' && (TerminalDevice->TerminalType == TerminalTypeVt100 ||\r
+                                 TerminalDevice->TerminalType == TerminalTypeTtyTerm)) {\r
         TerminalDevice->InputState |= INPUT_STATE_O;\r
         TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
         continue;\r
@@ -1291,8 +1386,8 @@ UnicodeToEfiKey (
 \r
       Key.ScanCode = SCAN_NULL;\r
 \r
-      if (TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
-          TerminalDevice->TerminalType == VTUTF8TYPE) {\r
+      if (TerminalDevice->TerminalType == TerminalTypeVt100Plus ||\r
+          TerminalDevice->TerminalType == TerminalTypeVtUtf8) {\r
         switch (UnicodeChar) {\r
         case '1':\r
           Key.ScanCode = SCAN_F1;\r
@@ -1358,14 +1453,14 @@ UnicodeToEfiKey (
         if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {\r
           TerminalDevice->ResetState = RESET_STATE_ESC_R;\r
           SetDefaultResetState = FALSE;\r
-        } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) {\r
+        } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_R) {\r
           gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
         }\r
         Key.ScanCode = SCAN_NULL;\r
         break;\r
       case 'r':\r
         if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {\r
-          TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r;\r
+          TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_R;\r
           SetDefaultResetState = FALSE;\r
         }\r
         Key.ScanCode = SCAN_NULL;\r
@@ -1380,7 +1475,7 @@ UnicodeToEfiKey (
 \r
       if (Key.ScanCode != SCAN_NULL) {\r
         Key.UnicodeChar = 0;\r
-        EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
+        EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
         TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
         UnicodeToEfiKeyFlushState (TerminalDevice);\r
         continue;\r
@@ -1396,7 +1491,7 @@ UnicodeToEfiKey (
 \r
       Key.ScanCode = SCAN_NULL;\r
 \r
-      if (TerminalDevice->TerminalType == VT100TYPE) {\r
+      if (TerminalDevice->TerminalType == TerminalTypeVt100) {\r
         switch (UnicodeChar) {\r
         case 'P':\r
           Key.ScanCode = SCAN_F1;\r
@@ -1431,11 +1526,33 @@ UnicodeToEfiKey (
         default :\r
           break;\r
         }\r
+      } else if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {\r
+        /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */\r
+        switch (UnicodeChar) {\r
+        case 'P':\r
+          Key.ScanCode = SCAN_F1;\r
+          break;\r
+        case 'Q':\r
+          Key.ScanCode = SCAN_F2;\r
+          break;\r
+        case 'R':\r
+          Key.ScanCode = SCAN_F3;\r
+          break;\r
+        case 'S':\r
+          Key.ScanCode = SCAN_F4;\r
+          break;\r
+        case 'H':\r
+          Key.ScanCode = SCAN_HOME;\r
+          break;\r
+        case 'F':\r
+          Key.ScanCode = SCAN_END;\r
+          break;\r
+        }\r
       }\r
 \r
       if (Key.ScanCode != SCAN_NULL) {\r
         Key.UnicodeChar = 0;\r
-        EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
+        EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
         TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
         UnicodeToEfiKeyFlushState (TerminalDevice);\r
         continue;\r
@@ -1451,10 +1568,11 @@ UnicodeToEfiKey (
 \r
       Key.ScanCode = SCAN_NULL;\r
 \r
-      if (TerminalDevice->TerminalType == PCANSITYPE    ||\r
-          TerminalDevice->TerminalType == VT100TYPE     ||\r
-          TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
-          TerminalDevice->TerminalType == VTUTF8TYPE) {\r
+      if (TerminalDevice->TerminalType == TerminalTypePcAnsi    ||\r
+          TerminalDevice->TerminalType == TerminalTypeVt100     ||\r
+          TerminalDevice->TerminalType == TerminalTypeVt100Plus ||\r
+          TerminalDevice->TerminalType == TerminalTypeVtUtf8    ||\r
+          TerminalDevice->TerminalType == TerminalTypeTtyTerm) {\r
         switch (UnicodeChar) {\r
         case 'A':\r
           Key.ScanCode = SCAN_UP;\r
@@ -1469,100 +1587,104 @@ UnicodeToEfiKey (
           Key.ScanCode = SCAN_LEFT;\r
           break;\r
         case 'H':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE ||\r
-              TerminalDevice->TerminalType == VT100TYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi ||\r
+              TerminalDevice->TerminalType == TerminalTypeVt100  ||\r
+              TerminalDevice->TerminalType == TerminalTypeTtyTerm) {\r
             Key.ScanCode = SCAN_HOME;\r
           }\r
           break;\r
         case 'F':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi ||\r
+              TerminalDevice->TerminalType == TerminalTypeTtyTerm) {\r
             Key.ScanCode = SCAN_END;\r
           }\r
           break;\r
         case 'K':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypeVt100) {\r
             Key.ScanCode = SCAN_END;\r
           }\r
           break;\r
         case 'L':\r
         case '@':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE ||\r
-              TerminalDevice->TerminalType == VT100TYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi ||\r
+              TerminalDevice->TerminalType == TerminalTypeVt100) {\r
             Key.ScanCode = SCAN_INSERT;\r
           }\r
           break;\r
         case 'X':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_DELETE;\r
           }\r
           break;\r
         case 'P':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypeVt100) {\r
             Key.ScanCode = SCAN_DELETE;\r
-          } else if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          } else if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F4;\r
           }\r
           break;\r
         case 'I':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_PAGE_UP;\r
           }\r
           break;\r
         case 'V':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F10;\r
           }\r
+          break;\r
         case '?':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypeVt100) {\r
             Key.ScanCode = SCAN_PAGE_UP;\r
           }\r
           break;\r
         case 'G':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_PAGE_DOWN;\r
           }\r
           break;\r
         case 'U':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F9;\r
           }\r
+          break;\r
         case '/':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypeVt100) {\r
             Key.ScanCode = SCAN_PAGE_DOWN;\r
           }\r
           break;\r
         case 'M':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F1;\r
           }\r
           break;\r
         case 'N':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F2;\r
           }\r
           break;\r
         case 'O':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F3;\r
           }\r
           break;\r
         case 'Q':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F5;\r
           }\r
           break;\r
         case 'R':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F6;\r
           }\r
           break;\r
         case 'S':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F7;\r
           }\r
           break;\r
         case 'T':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
+          if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {\r
             Key.ScanCode = SCAN_F8;\r
           }\r
           break;\r
@@ -1571,9 +1693,24 @@ UnicodeToEfiKey (
         }\r
       }\r
 \r
+      /*\r
+       * The VT220 escape codes that the TTY terminal accepts all have\r
+       * numeric codes, and there are no ambiguous prefixes shared with\r
+       * other terminal types.\r
+       */\r
+      if (TerminalDevice->TerminalType == TerminalTypeTtyTerm &&\r
+          Key.ScanCode == SCAN_NULL &&\r
+          UnicodeChar >= '0' &&\r
+          UnicodeChar <= '9') {\r
+        TerminalDevice->TtyEscapeStr[0] = UnicodeChar;\r
+        TerminalDevice->TtyEscapeIndex = 1;\r
+        TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET_2;\r
+        continue;\r
+      }\r
+\r
       if (Key.ScanCode != SCAN_NULL) {\r
         Key.UnicodeChar = 0;\r
-        EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
+        EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
         TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
         UnicodeToEfiKeyFlushState (TerminalDevice);\r
         continue;\r
@@ -1584,6 +1721,74 @@ UnicodeToEfiKey (
       break;\r
 \r
 \r
+    case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_LEFTOPENBRACKET_2:\r
+      /*\r
+       * Here we handle the VT220 escape codes that we accept.  This\r
+       * state is only used by the TTY terminal type.\r
+       */\r
+      Key.ScanCode = SCAN_NULL;\r
+      if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {\r
+\r
+        if (UnicodeChar == '~' && TerminalDevice->TtyEscapeIndex <= 2) {\r
+          UINT16 EscCode;\r
+          TerminalDevice->TtyEscapeStr[TerminalDevice->TtyEscapeIndex] = 0; /* Terminate string */\r
+          EscCode = (UINT16) StrDecimalToUintn(TerminalDevice->TtyEscapeStr);\r
+          switch (EscCode) {\r
+          case 2:\r
+              Key.ScanCode = SCAN_INSERT;\r
+              break;\r
+          case 3:\r
+              Key.ScanCode = SCAN_DELETE;\r
+              break;\r
+          case 5:\r
+              Key.ScanCode = SCAN_PAGE_UP;\r
+              break;\r
+          case 6:\r
+              Key.ScanCode = SCAN_PAGE_DOWN;\r
+              break;\r
+          case 11:\r
+          case 12:\r
+          case 13:\r
+          case 14:\r
+          case 15:\r
+            Key.ScanCode = SCAN_F1 + EscCode - 11;\r
+            break;\r
+          case 17:\r
+          case 18:\r
+          case 19:\r
+          case 20:\r
+          case 21:\r
+            Key.ScanCode = SCAN_F6 + EscCode - 17;\r
+            break;\r
+          case 23:\r
+          case 24:\r
+            Key.ScanCode = SCAN_F11 + EscCode - 23;\r
+            break;\r
+          default:\r
+            break;\r
+          }\r
+        } else if (TerminalDevice->TtyEscapeIndex == 1){\r
+          /* 2 character escape code   */\r
+          TerminalDevice->TtyEscapeStr[TerminalDevice->TtyEscapeIndex++] = UnicodeChar;\r
+          continue;\r
+        }\r
+        else {\r
+          DEBUG ((EFI_D_ERROR, "Unexpected state in escape2\n"));\r
+        }\r
+      }\r
+      TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
+\r
+      if (Key.ScanCode != SCAN_NULL) {\r
+        Key.UnicodeChar = 0;\r
+        EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
+        TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
+        UnicodeToEfiKeyFlushState (TerminalDevice);\r
+        continue;\r
+      }\r
+\r
+      UnicodeToEfiKeyFlushState (TerminalDevice);\r
+      break;\r
+\r
     default:\r
       //\r
       // Invalid state. This should never happen.\r
@@ -1618,13 +1823,19 @@ UnicodeToEfiKey (
     }\r
 \r
     if (UnicodeChar == DEL) {\r
-      Key.ScanCode    = SCAN_DELETE;\r
-      Key.UnicodeChar = 0;\r
+      if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {\r
+        Key.ScanCode    = SCAN_NULL;\r
+        Key.UnicodeChar = CHAR_BACKSPACE;\r
+      }\r
+      else {\r
+        Key.ScanCode    = SCAN_DELETE;\r
+        Key.UnicodeChar = 0;\r
+      }\r
     } else {\r
       Key.ScanCode    = SCAN_NULL;\r
       Key.UnicodeChar = UnicodeChar;\r
     }\r
 \r
-    EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
   }\r
 }\r