]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Fix TerminalDxe FIFO Data Loss
authorniruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 8 Oct 2011 02:09:50 +0000 (02:09 +0000)
committerniruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 8 Oct 2011 02:09:50 +0000 (02:09 +0000)
Fixes a Terminal FIFO full issue that caused data to be lost. The Unicode and EFI Key FIFOs are now checked to make sure they have spaces before pushing another entry.

Signed-off-by: eugenecohen
Reviewed-by: niruiyu
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12512 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/Console/TerminalDxe/Ansi.c
MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
MdeModulePkg/Universal/Console/TerminalDxe/Vtutf8.c

index 4ebd7c9f462d431fab6bd3326f3b751e35386925..4f84cc09ce9e39d99368d4fb53d16d1963d0c460 100644 (file)
@@ -1,79 +1,79 @@
-/** @file\r
-  Implementation of translation upon PC ANSI.\r
-\r
-Copyright (c) 2006 - 2008, 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
-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
-\r
-**/\r
-\r
-\r
-#include "Terminal.h"\r
-\r
-/**\r
-  Translate all raw data in the Raw FIFO into unicode, and insert\r
-  them into Unicode FIFO.\r
-\r
-  @param TerminalDevice          The terminal device.\r
-\r
-**/\r
-VOID\r
-AnsiRawDataToUnicode (\r
-  IN  TERMINAL_DEV    *TerminalDevice\r
-  )\r
-{\r
-  UINT8 RawData;\r
-\r
-  //\r
-  // pop the raw data out from the raw fifo,\r
-  // and translate it into unicode, then push\r
-  // the unicode into unicode fifo, until the raw fifo is empty.\r
-  //\r
-  while (!IsRawFiFoEmpty (TerminalDevice)) {\r
-\r
-    RawFiFoRemoveOneKey (TerminalDevice, &RawData);\r
-\r
-    UnicodeFiFoInsertOneKey (TerminalDevice, (UINT16) RawData);\r
-  }\r
-}\r
-\r
-/**\r
-  Check if input string is valid Ascii string, valid EFI control characters\r
-  or valid text graphics.\r
-\r
-  @param  TerminalDevice          The terminal device.\r
-  @param  WString                 The input string.          \r
\r
-  @retval EFI_UNSUPPORTED         If not all input characters are valid.\r
-  @retval EFI_SUCCESS             If all input characters are valid.\r
-\r
-**/\r
-EFI_STATUS\r
-AnsiTestString (\r
-  IN  TERMINAL_DEV    *TerminalDevice,\r
-  IN  CHAR16          *WString\r
-  )\r
-{\r
-  CHAR8 GraphicChar;\r
-\r
-  //\r
-  // support three kind of character:\r
-  // valid ascii, valid efi control char, valid text graphics.\r
-  //\r
-  for (; *WString != CHAR_NULL; WString++) {\r
-\r
-    if ( !(TerminalIsValidAscii (*WString) ||\r
-        TerminalIsValidEfiCntlChar (*WString) ||\r
-        TerminalIsValidTextGraphics (*WString, &GraphicChar, NULL) )) {\r
-\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
+/** @file
+  Implementation of translation upon PC ANSI.
+
+Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "Terminal.h"
+
+/**
+  Translate all raw data in the Raw FIFO into unicode, and insert
+  them into Unicode FIFO.
+
+  @param TerminalDevice          The terminal device.
+
+**/
+VOID
+AnsiRawDataToUnicode (
+  IN  TERMINAL_DEV    *TerminalDevice
+  )
+{
+  UINT8 RawData;
+
+  //
+  // pop the raw data out from the raw fifo,
+  // and translate it into unicode, then push
+  // the unicode into unicode fifo, until the raw fifo is empty.
+  //
+  while (!IsRawFiFoEmpty (TerminalDevice) && !IsUnicodeFiFoFull(TerminalDevice) ) {
+
+    RawFiFoRemoveOneKey (TerminalDevice, &RawData);
+
+    UnicodeFiFoInsertOneKey (TerminalDevice, (UINT16) RawData);
+  }
+}
+
+/**
+  Check if input string is valid Ascii string, valid EFI control characters
+  or valid text graphics.
+
+  @param  TerminalDevice          The terminal device.
+  @param  WString                 The input string.          
+  @retval EFI_UNSUPPORTED         If not all input characters are valid.
+  @retval EFI_SUCCESS             If all input characters are valid.
+
+**/
+EFI_STATUS
+AnsiTestString (
+  IN  TERMINAL_DEV    *TerminalDevice,
+  IN  CHAR16          *WString
+  )
+{
+  CHAR8 GraphicChar;
+
+  //
+  // support three kind of character:
+  // valid ascii, valid efi control char, valid text graphics.
+  //
+  for (; *WString != CHAR_NULL; WString++) {
+
+    if ( !(TerminalIsValidAscii (*WString) ||
+        TerminalIsValidEfiCntlChar (*WString) ||
+        TerminalIsValidTextGraphics (*WString, &GraphicChar, NULL) )) {
+
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
index b5dbaf92807241387ed031fd5ac89f9b7dbd5533..662cd5682f74cb038a9c677b478b3e14fb974ca9 100644 (file)
-/** @file\r
-  Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.\r
-\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
-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
-\r
-**/\r
-\r
-#include "Terminal.h"\r
-\r
-\r
-/**\r
-  Reads the next keystroke from the input device. The WaitForKey Event can\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
-                                   keystroke state data for the key that was\r
-                                   pressed.\r
-\r
-  @retval EFI_SUCCESS              The keystroke information was returned.\r
-  @retval EFI_NOT_READY            There was no keystroke data available.\r
-  @retval EFI_INVALID_PARAMETER    KeyData is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-ReadKeyStrokeWorker (\r
-  IN  TERMINAL_DEV *TerminalDevice,\r
-  OUT EFI_KEY_DATA *KeyData\r
-  )\r
-{\r
-  if (KeyData == NULL) {\r
-    return EFI_INVALID_PARAMETER;\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
-  return EFI_SUCCESS;\r
-\r
-}\r
-\r
-/**\r
-  Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().\r
-  This driver only perform dependent serial device reset regardless of\r
-  the value of ExtendeVerification\r
-\r
-  @param  This                     Indicates the calling context.\r
-  @param  ExtendedVerification     Skip by this driver.\r
-\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
-EFIAPI\r
-TerminalConInReset (\r
-  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
-  IN  BOOLEAN                         ExtendedVerification\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-  TERMINAL_DEV  *TerminalDevice;\r
-\r
-  TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
-\r
-  //\r
-  // Report progress code here\r
-  //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-    EFI_PROGRESS_CODE,\r
-    (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),\r
-    TerminalDevice->DevicePath\r
-    );\r
-\r
-  Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);\r
-\r
-  //\r
-  // Make all the internal buffer empty for keys\r
-  //\r
-  TerminalDevice->RawFiFo->Head     = TerminalDevice->RawFiFo->Tail;\r
-  TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail;\r
-  TerminalDevice->EfiKeyFiFo->Head  = TerminalDevice->EfiKeyFiFo->Tail;\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-      (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\r
-      TerminalDevice->DevicePath\r
-      );\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().\r
-\r
-  @param  This                Indicates the calling context.\r
-  @param  Key                 A pointer to a buffer that is filled in with the\r
-                              keystroke information for the key that was sent\r
-                              from terminal.\r
-\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
-EFIAPI\r
-TerminalConInReadKeyStroke (\r
-  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
-  OUT EFI_INPUT_KEY                   *Key\r
-  )\r
-{\r
-  TERMINAL_DEV  *TerminalDevice;\r
-  EFI_STATUS    Status;\r
-  EFI_KEY_DATA  KeyData;\r
-\r
-  //\r
-  //  get TERMINAL_DEV from "This" parameter.\r
-  //\r
-  TerminalDevice  = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
-\r
-  Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
-\r
-  return EFI_SUCCESS;\r
-\r
-}\r
-\r
-/**\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
-  @param  InputData                A pointer to a buffer that is filled in with the\r
-                                   keystroke state data for the key that was\r
-                                   pressed.\r
-\r
-  @retval TRUE                     Key be pressed matches a registered key.\r
-  @retval FLASE                    Match failed.\r
-\r
-**/\r
-BOOLEAN\r
-IsKeyRegistered (\r
-  IN EFI_KEY_DATA  *RegsiteredData,\r
-  IN EFI_KEY_DATA  *InputData\r
-  )\r
-{\r
-  ASSERT (RegsiteredData != NULL && InputData != NULL);\r
-\r
-  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||\r
-      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-\r
-\r
-/**\r
-  Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event\r
-  Signal the event if there is key available\r
-\r
-  @param  Event                    Indicates the event that invoke this function.\r
-  @param  Context                  Indicates the calling context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-TerminalConInWaitForKeyEx (\r
-  IN  EFI_EVENT       Event,\r
-  IN  VOID            *Context\r
-  )\r
-{\r
-  TerminalConInWaitForKey (Event, Context);\r
-}\r
-\r
-//\r
-// Simple Text Input Ex protocol functions\r
-//\r
-\r
-/**\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
-\r
-  @retval EFI_SUCCESS              The device was reset.\r
-  @retval EFI_DEVICE_ERROR         The device is not functioning properly and could\r
-                                   not be reset.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TerminalConInResetEx (\r
-  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
-  IN BOOLEAN                            ExtendedVerification\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  TERMINAL_DEV            *TerminalDevice;\r
-\r
-  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
-\r
-  Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-\r
-}\r
-\r
-\r
-/**\r
-  Reads the next keystroke from the input device. The WaitForKey Event can\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
-                                   keystroke state data for the key that was\r
-                                   pressed.\r
-\r
-  @retval EFI_SUCCESS              The keystroke information was returned.\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
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TerminalConInReadKeyStrokeEx (\r
-  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
-  OUT EFI_KEY_DATA                      *KeyData\r
-  )\r
-{\r
-  TERMINAL_DEV                    *TerminalDevice;\r
-\r
-  if (KeyData == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
-\r
-  return ReadKeyStrokeWorker (TerminalDevice, KeyData);\r
-\r
-}\r
-\r
-\r
-/**\r
-  Set certain state for the input device.\r
-\r
-  @param  This                     Protocol instance pointer.\r
-  @param  KeyToggleState           A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
-                                   state for the input device.\r
-\r
-  @retval EFI_SUCCESS              The device state was set successfully.\r
-  @retval EFI_DEVICE_ERROR         The device is not functioning correctly and\r
-                                   could not have the setting adjusted.\r
-  @retval EFI_UNSUPPORTED          The device does not have the ability to set its\r
-                                   state.\r
-  @retval EFI_INVALID_PARAMETER    KeyToggleState is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TerminalConInSetState (\r
-  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
-  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
-  )\r
-{\r
-  if (KeyToggleState == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  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  KeyNotificationFunction  Points to the function to be called when the key\r
-                                   sequence is typed specified by KeyData.\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 necessary data\r
-                                   structures.\r
-  @retval EFI_INVALID_PARAMETER    KeyData or NotifyHandle is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TerminalConInRegisterKeyNotify (\r
-  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
-  IN EFI_KEY_DATA                       *KeyData,\r
-  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,\r
-  OUT EFI_HANDLE                        *NotifyHandle\r
-  )\r
-{\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
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
-\r
-  //\r
-  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already 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
-      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
-        *NotifyHandle = CurrentNotify->NotifyHandle;\r
-        return EFI_SUCCESS;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // Allocate resource to save the notification function\r
-  //\r
-  NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));\r
-  if (NewNotify == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  NewNotify->Signature         = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
-  NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
-  NewNotify->NotifyHandle      = (EFI_HANDLE) NewNotify;\r
-  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
-  InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);\r
-\r
-  *NotifyHandle                = NewNotify->NotifyHandle;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Remove a registered notification function from a particular keystroke.\r
-\r
-  @param  This                     Protocol instance pointer.\r
-  @param  NotificationHandle       The handle of the notification function being\r
-                                   unregistered.\r
-\r
-  @retval EFI_SUCCESS              The notification function was unregistered\r
-                                   successfully.\r
-  @retval EFI_INVALID_PARAMETER    The NotificationHandle is invalid.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TerminalConInUnregisterKeyNotify (\r
-  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
-  IN EFI_HANDLE                         NotificationHandle\r
-  )\r
-{\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
-  if (((TERMINAL_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
-    return EFI_INVALID_PARAMETER;\r
-  } \r
-  \r
-  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\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 (CurrentNotify->NotifyHandle == NotificationHandle) {\r
-      //\r
-      // Remove the notification function from NotifyList and free resources\r
-      //\r
-      RemoveEntryList (&CurrentNotify->NotifyEntry);\r
-\r
-      gBS->FreePool (CurrentNotify);\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-\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
-\r
-  @param  TerminalDevice       Terminal driver private structure.\r
-\r
-**/\r
-VOID\r
-TranslateRawDataToEfiKey (\r
-  IN  TERMINAL_DEV      *TerminalDevice\r
-  )\r
-{\r
-  switch (TerminalDevice->TerminalType) {\r
-\r
-  case PCANSITYPE:\r
-  case VT100TYPE:\r
-  case VT100PLUSTYPE:\r
-    AnsiRawDataToUnicode (TerminalDevice);\r
-    UnicodeToEfiKey (TerminalDevice);\r
-    break;\r
-\r
-  case VTUTF8TYPE:\r
-    //\r
-    // Process all the raw data in the RawFIFO,\r
-    // put the processed key into UnicodeFIFO.\r
-    //\r
-    VTUTF8RawDataToUnicode (TerminalDevice);\r
-\r
-    //\r
-    // Translate all the Unicode data in the UnicodeFIFO to Efi key,\r
-    // then put into EfiKeyFIFO.\r
-    //\r
-    UnicodeToEfiKey (TerminalDevice);\r
-\r
-    break;\r
-  }\r
-}\r
-\r
-/**\r
-  Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event\r
-  Signal the event if there is key available\r
-\r
-  @param  Event                    Indicates the event that invoke this function.\r
-  @param  Context                  Indicates the calling context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-TerminalConInWaitForKey (\r
-  IN  EFI_EVENT       Event,\r
-  IN  VOID            *Context\r
-  )\r
-{\r
-  //\r
-  // Someone is waiting on the keystroke event, if there's\r
-  // a key pending, signal the event\r
-  //\r
-  if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) {\r
-\r
-    gBS->SignalEvent (Event);\r
-  }\r
-}\r
-\r
-/**\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
-VOID\r
-EFIAPI\r
-TerminalConInTimerHandler (\r
-  IN EFI_EVENT            Event,\r
-  IN VOID                 *Context\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  TERMINAL_DEV            *TerminalDevice;\r
-  UINT8                   Input;\r
-  EFI_SERIAL_IO_MODE      *Mode;\r
-  EFI_SERIAL_IO_PROTOCOL  *SerialIo;\r
-  UINTN                   SerialInTimeOut;\r
-\r
-  TerminalDevice  = (TERMINAL_DEV *) Context;\r
-\r
-  SerialIo        = TerminalDevice->SerialIo;\r
-  if (SerialIo == NULL) {\r
-    return ;\r
-  }\r
-  //\r
-  //  if current timeout value for serial device is not identical with\r
-  //  the value saved in TERMINAL_DEV structure, then recalculate the\r
-  //  timeout value again and set serial attribute according to this value.\r
-  //\r
-  Mode = SerialIo->Mode;\r
-  if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {\r
-\r
-    SerialInTimeOut = 0;\r
-    if (Mode->BaudRate != 0) {\r
-      //\r
-      // According to BAUD rate to calculate the timeout value.\r
-      //\r
-      SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
-    }\r
-\r
-    Status = SerialIo->SetAttributes (\r
-                        SerialIo,\r
-                        Mode->BaudRate,\r
-                        Mode->ReceiveFifoDepth,\r
-                        (UINT32) SerialInTimeOut,\r
-                        (EFI_PARITY_TYPE) (Mode->Parity),\r
-                        (UINT8) Mode->DataBits,\r
-                        (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
-                        );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      TerminalDevice->SerialInTimeOut = 0;\r
-    } else {\r
-      TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Fetch all the keys in the serial buffer,\r
-  // and insert the byte stream into RawFIFO.\r
-  //\r
-  do {\r
-\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
-          (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR),\r
-          TerminalDevice->DevicePath\r
-          );\r
-      }\r
-      break;\r
-    }\r
-\r
-    RawFiFoInsertOneKey (TerminalDevice, Input);\r
-  } while (TRUE);\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
-/**\r
-  Get one key out of serial buffer.\r
-\r
-  @param  SerialIo           Serial I/O protocol attached to the serial device.\r
-  @param  Output             The fetched key.\r
-\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
-EFI_STATUS\r
-GetOneKeyFromSerial (\r
-  EFI_SERIAL_IO_PROTOCOL  *SerialIo,\r
-  UINT8                   *Output\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINTN       Size;\r
-\r
-  Size    = 1;\r
-  *Output = 0;\r
-\r
-  //\r
-  // Read one key from serial I/O device.\r
-  //\r
-  Status  = SerialIo->Read (SerialIo, &Size, Output);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-\r
-    if (Status == EFI_TIMEOUT) {\r
-      return EFI_NOT_READY;\r
-    }\r
-\r
-    return EFI_DEVICE_ERROR;\r
-\r
-  }\r
-\r
-  if (*Output == 0) {\r
-    return EFI_NOT_READY;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Insert one byte raw data into the Raw Data FIFO.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure.\r
-  @param  Input                The key will be input.\r
-\r
-  @retval TRUE                 If insert successfully.\r
-  @retval FLASE                If Raw Data buffer is full before key insertion,\r
-                               and the key is lost.\r
-\r
-**/\r
-BOOLEAN\r
-RawFiFoInsertOneKey (\r
-  TERMINAL_DEV      *TerminalDevice,\r
-  UINT8             Input\r
-  )\r
-{\r
-  UINT8 Tail;\r
-\r
-  Tail = TerminalDevice->RawFiFo->Tail;\r
-\r
-  if (IsRawFiFoFull (TerminalDevice)) {\r
-    //\r
-    // Raw FIFO is full\r
-    //\r
-    return FALSE;\r
-  }\r
-\r
-  TerminalDevice->RawFiFo->Data[Tail]  = Input;\r
-\r
-  TerminalDevice->RawFiFo->Tail        = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Remove one pre-fetched key out of the Raw Data FIFO.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure.\r
-  @param  Output               The key will be removed.\r
-\r
-  @retval TRUE                 If insert successfully.\r
-  @retval FLASE                If Raw Data FIFO buffer is empty before remove operation.\r
-\r
-**/\r
-BOOLEAN\r
-RawFiFoRemoveOneKey (\r
-  TERMINAL_DEV  *TerminalDevice,\r
-  UINT8         *Output\r
-  )\r
-{\r
-  UINT8 Head;\r
-\r
-  Head = TerminalDevice->RawFiFo->Head;\r
-\r
-  if (IsRawFiFoEmpty (TerminalDevice)) {\r
-    //\r
-    //  FIFO is empty\r
-    //\r
-    *Output = 0;\r
-    return FALSE;\r
-  }\r
-\r
-  *Output                       = TerminalDevice->RawFiFo->Data[Head];\r
-\r
-  TerminalDevice->RawFiFo->Head  = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Clarify whether Raw Data FIFO buffer is empty.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure\r
-\r
-  @retval TRUE                 If Raw Data FIFO buffer is empty.\r
-  @retval FLASE                If Raw Data FIFO buffer is not empty.\r
-\r
-**/\r
-BOOLEAN\r
-IsRawFiFoEmpty (\r
-  TERMINAL_DEV  *TerminalDevice\r
-  )\r
-{\r
-  if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {\r
-    return TRUE;\r
-  } else {\r
-    return FALSE;\r
-  }\r
-}\r
-\r
-/**\r
-  Clarify whether Raw Data FIFO buffer is full.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure\r
-\r
-  @retval TRUE                 If Raw Data FIFO buffer is full.\r
-  @retval FLASE                If Raw Data FIFO buffer is not full.\r
-\r
-**/\r
-BOOLEAN\r
-IsRawFiFoFull (\r
-  TERMINAL_DEV  *TerminalDevice\r
-  )\r
-{\r
-  UINT8 Tail;\r
-  UINT8 Head;\r
-\r
-  Tail  = TerminalDevice->RawFiFo->Tail;\r
-  Head  = TerminalDevice->RawFiFo->Head;\r
-\r
-  if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {\r
-\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
-  @retval TRUE                 If insert successfully.\r
-  @retval FLASE                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
-  )\r
-{\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
-  CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));\r
-  KeyData.KeyState.KeyShiftState  = 0;\r
-  KeyData.KeyState.KeyToggleState = 0;\r
-\r
-  //\r
-  // Invoke notification functions if exist\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
-      CurrentNotify->KeyNotificationFn (&KeyData);\r
-    }\r
-  }\r
-  if (IsEfiKeyFiFoFull (TerminalDevice)) {\r
-    //\r
-    // Efi Key FIFO is full\r
-    //\r
-    return FALSE;\r
-  }\r
-\r
-  CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));\r
-\r
-  TerminalDevice->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  TerminalDevice       Terminal driver private structure.\r
-  @param  Output               The key will be removed.\r
-\r
-  @retval TRUE                 If insert successfully.\r
-  @retval FLASE                If FIFO buffer is empty before remove operation.\r
-\r
-**/\r
-BOOLEAN\r
-EfiKeyFiFoRemoveOneKey (\r
-  TERMINAL_DEV  *TerminalDevice,\r
-  EFI_INPUT_KEY *Output\r
-  )\r
-{\r
-  UINT8 Head;\r
-\r
-  Head = TerminalDevice->EfiKeyFiFo->Head;\r
-  ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
-\r
-  if (IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
-    //\r
-    //  FIFO is empty\r
-    //\r
-    Output->ScanCode    = SCAN_NULL;\r
-    Output->UnicodeChar = 0;\r
-    return FALSE;\r
-  }\r
-\r
-  *Output                         = TerminalDevice->EfiKeyFiFo->Data[Head];\r
-\r
-  TerminalDevice->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  TerminalDevice       Terminal driver private structure\r
-\r
-  @retval TRUE                 If FIFO buffer is empty.\r
-  @retval FLASE                If FIFO buffer is not empty.\r
-\r
-**/\r
-BOOLEAN\r
-IsEfiKeyFiFoEmpty (\r
-  TERMINAL_DEV  *TerminalDevice\r
-  )\r
-{\r
-  if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {\r
-    return TRUE;\r
-  } else {\r
-    return FALSE;\r
-  }\r
-}\r
-\r
-/**\r
-  Clarify whether FIFO buffer is full.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure\r
-\r
-  @retval TRUE                 If FIFO buffer is full.\r
-  @retval FLASE                If FIFO buffer is not full.\r
-\r
-**/\r
-BOOLEAN\r
-IsEfiKeyFiFoFull (\r
-  TERMINAL_DEV  *TerminalDevice\r
-  )\r
-{\r
-  UINT8 Tail;\r
-  UINT8 Head;\r
-\r
-  Tail  = TerminalDevice->EfiKeyFiFo->Tail;\r
-  Head  = TerminalDevice->EfiKeyFiFo->Head;\r
-\r
-  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
-\r
-    return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Insert one pre-fetched key into the Unicode FIFO buffer.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure.\r
-  @param  Input                The key will be input.\r
-\r
-  @retval TRUE                 If insert successfully.\r
-  @retval FLASE                If Unicode FIFO buffer is full before key insertion,\r
-                               and the key is lost.\r
-\r
-**/\r
-BOOLEAN\r
-UnicodeFiFoInsertOneKey (\r
-  TERMINAL_DEV      *TerminalDevice,\r
-  UINT16            Input\r
-  )\r
-{\r
-  UINT8 Tail;\r
-\r
-  Tail = TerminalDevice->UnicodeFiFo->Tail;\r
-  ASSERT (Tail < FIFO_MAX_NUMBER + 1);\r
-\r
-\r
-  if (IsUnicodeFiFoFull (TerminalDevice)) {\r
-    //\r
-    // Unicode FIFO is full\r
-    //\r
-    return FALSE;\r
-  }\r
-\r
-  TerminalDevice->UnicodeFiFo->Data[Tail]  = Input;\r
-\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
-\r
-  @param  TerminalDevice       Terminal driver private structure.\r
-  @param  Output               The key will be removed.\r
-\r
-  @retval TRUE                 If insert successfully.\r
-  @retval FLASE                If Unicode FIFO buffer is empty before remove operation.\r
-\r
-**/\r
-BOOLEAN\r
-UnicodeFiFoRemoveOneKey (\r
-  TERMINAL_DEV  *TerminalDevice,\r
-  UINT16        *Output\r
-  )\r
-{\r
-  UINT8 Head;\r
-\r
-  Head = TerminalDevice->UnicodeFiFo->Head;\r
-  ASSERT (Head < FIFO_MAX_NUMBER + 1);\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
-\r
-  TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Clarify whether Unicode FIFO buffer is empty.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure\r
-\r
-  @retval TRUE                 If Unicode FIFO buffer is empty.\r
-  @retval FLASE                If Unicode FIFO buffer is not empty.\r
-\r
-**/\r
-BOOLEAN\r
-IsUnicodeFiFoEmpty (\r
-  TERMINAL_DEV  *TerminalDevice\r
-  )\r
-{\r
-  if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {\r
-    return TRUE;\r
-  } else {\r
-    return FALSE;\r
-  }\r
-}\r
-\r
-/**\r
-  Clarify whether Unicode FIFO buffer is full.\r
-\r
-  @param  TerminalDevice       Terminal driver private structure\r
-\r
-  @retval TRUE                 If Unicode FIFO buffer is full.\r
-  @retval FLASE                If Unicode FIFO buffer is not full.\r
-\r
-**/\r
-BOOLEAN\r
-IsUnicodeFiFoFull (\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 + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
-\r
-    return TRUE;\r
-  }\r
-\r
-  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
-**/\r
-VOID\r
-UnicodeToEfiKeyFlushState (\r
-  IN  TERMINAL_DEV    *TerminalDevice\r
-  )\r
-{\r
-  EFI_INPUT_KEY Key;\r
-  UINT32        InputState;\r
-\r
-  InputState = TerminalDevice->InputState;\r
-\r
-  if ((InputState & INPUT_STATE_ESC) != 0) {\r
-    Key.ScanCode    = SCAN_ESC;\r
-    Key.UnicodeChar = 0;\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
-  }\r
-\r
-  if ((InputState & INPUT_STATE_CSI) != 0) {\r
-    Key.ScanCode    = SCAN_NULL;\r
-    Key.UnicodeChar = CSI;\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
-  }\r
-\r
-  if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {\r
-    Key.ScanCode    = SCAN_NULL;\r
-    Key.UnicodeChar = LEFTOPENBRACKET;\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
-  }\r
-\r
-  if ((InputState & INPUT_STATE_O) != 0) {\r
-    Key.ScanCode    = SCAN_NULL;\r
-    Key.UnicodeChar = 'O';\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
-  }\r
-\r
-  if ((InputState & INPUT_STATE_2) != 0) {\r
-    Key.ScanCode    = SCAN_NULL;\r
-    Key.UnicodeChar = '2';\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
-  }\r
-\r
-  //\r
-  // Cancel the timer.\r
-  //\r
-  gBS->SetTimer (\r
-        TerminalDevice->TwoSecondTimeOut,\r
-        TimerCancel,\r
-        0\r
-        );\r
-\r
-  TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
-}\r
-\r
-\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
-  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 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
-  completed in 2 seconds, then the raw key strokes of the partial ESC sequence are\r
-  converted into EFI Keys.\r
-  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
-    CSI = 0x9B\r
-    DEL = 0x7f\r
-    ^   = CTRL\r
-\r
-  +=========+======+===========+==========+==========+\r
-  |         | EFI  | UEFI 2.0  |          |          |\r
-  |         | Scan |           |  VT100+  |          |\r
-  |   KEY   | Code |  PC ANSI  |  VTUTF8  |   VT100  |\r
-  +=========+======+===========+==========+==========+\r
-  | NULL    | 0x00 |           |          |          |\r
-  | UP      | 0x01 | ESC [ A   | ESC [ A  | ESC [ A  |\r
-  | DOWN    | 0x02 | ESC [ B   | ESC [ B  | ESC [ B  |\r
-  | RIGHT   | 0x03 | ESC [ C   | ESC [ C  | ESC [ C  |\r
-  | LEFT    | 0x04 | ESC [ D   | ESC [ D  | ESC [ D  |\r
-  | HOME    | 0x05 | ESC [ H   | ESC h    | ESC [ H  |\r
-  | END     | 0x06 | ESC [ F   | ESC k    | ESC [ K  |\r
-  | INSERT  | 0x07 | ESC [ @   | ESC +    | ESC [ @  |\r
-  |         |      | ESC [ L   |          | ESC [ L  |\r
-  | DELETE  | 0x08 | ESC [ X   | ESC -    | ESC [ P  |\r
-  | PG UP   | 0x09 | ESC [ I   | ESC ?    | ESC [ V  |\r
-  |         |      |           |          | ESC [ ?  |\r
-  | PG DOWN | 0x0A | ESC [ G   | ESC /    | ESC [ U  |\r
-  |         |      |           |          | ESC [ /  |\r
-  | F1      | 0x0B | ESC [ M   | ESC 1    | ESC O P  |\r
-  | F2      | 0x0C | ESC [ N   | ESC 2    | ESC O Q  |\r
-  | F3      | 0x0D | ESC [ O   | ESC 3    | ESC O w  |\r
-  | F4      | 0x0E | ESC [ P   | ESC 4    | ESC O x  |\r
-  | F5      | 0x0F | ESC [ Q   | ESC 5    | ESC O t  |\r
-  | F6      | 0x10 | ESC [ R   | ESC 6    | ESC O u  |\r
-  | F7      | 0x11 | ESC [ S   | ESC 7    | ESC O q  |\r
-  | F8      | 0x12 | ESC [ T   | ESC 8    | ESC O r  |\r
-  | F9      | 0x13 | ESC [ U   | ESC 9    | ESC O p  |\r
-  | F10     | 0x14 | ESC [ V   | ESC 0    | ESC O M  |\r
-  | Escape  | 0x17 | ESC       | ESC      | ESC      |\r
-  | F11     | 0x15 |           | ESC !    |          |\r
-  | F12     | 0x16 |           | ESC @    |          |\r
-  +=========+======+===========+==========+==========+\r
-\r
-  Special Mappings\r
-  ================\r
-  ESC R ESC r ESC R = Reset System\r
-\r
-  @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys\r
-\r
-**/\r
-VOID\r
-UnicodeToEfiKey (\r
-  IN  TERMINAL_DEV    *TerminalDevice\r
-  )\r
-{\r
-  EFI_STATUS          Status;\r
-  EFI_STATUS          TimerStatus;\r
-  UINT16              UnicodeChar;\r
-  EFI_INPUT_KEY       Key;\r
-  BOOLEAN             SetDefaultResetState;\r
-\r
-  TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
-\r
-  if (!EFI_ERROR (TimerStatus)) {\r
-    UnicodeToEfiKeyFlushState (TerminalDevice);\r
-    TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-  }\r
-\r
-  while (!IsUnicodeFiFoEmpty(TerminalDevice)) {\r
-\r
-    if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
-      //\r
-      // Check to see if the 2 seconds timer has expired\r
-      //\r
-      TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
-      if (!EFI_ERROR (TimerStatus)) {\r
-        UnicodeToEfiKeyFlushState (TerminalDevice);\r
-        TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Fetch one Unicode character from the Unicode FIFO\r
-    //\r
-    UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);\r
-\r
-    SetDefaultResetState = TRUE;\r
-\r
-    switch (TerminalDevice->InputState) {\r
-    case INPUT_STATE_DEFAULT:\r
-\r
-      break;\r
-\r
-    case INPUT_STATE_ESC:\r
-\r
-      if (UnicodeChar == LEFTOPENBRACKET) {\r
-        TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;\r
-        TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-        continue;\r
-      }\r
-\r
-      if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {\r
-        TerminalDevice->InputState |= INPUT_STATE_O;\r
-        TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-        continue;\r
-      }\r
-\r
-      Key.ScanCode = SCAN_NULL;\r
-\r
-      if (TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
-          TerminalDevice->TerminalType == VTUTF8TYPE) {\r
-        switch (UnicodeChar) {\r
-        case '1':\r
-          Key.ScanCode = SCAN_F1;\r
-          break;\r
-        case '2':\r
-          Key.ScanCode = SCAN_F2;\r
-          break;\r
-        case '3':\r
-          Key.ScanCode = SCAN_F3;\r
-          break;\r
-        case '4':\r
-          Key.ScanCode = SCAN_F4;\r
-          break;\r
-        case '5':\r
-          Key.ScanCode = SCAN_F5;\r
-          break;\r
-        case '6':\r
-          Key.ScanCode = SCAN_F6;\r
-          break;\r
-        case '7':\r
-          Key.ScanCode = SCAN_F7;\r
-          break;\r
-        case '8':\r
-          Key.ScanCode = SCAN_F8;\r
-          break;\r
-        case '9':\r
-          Key.ScanCode = SCAN_F9;\r
-          break;\r
-        case '0':\r
-          Key.ScanCode = SCAN_F10;\r
-          break;\r
-        case '!':\r
-          Key.ScanCode = SCAN_F11;\r
-          break;\r
-        case '@':\r
-          Key.ScanCode = SCAN_F12;\r
-          break;\r
-        case 'h':\r
-          Key.ScanCode = SCAN_HOME;\r
-          break;\r
-        case 'k':\r
-          Key.ScanCode = SCAN_END;\r
-          break;\r
-        case '+':\r
-          Key.ScanCode = SCAN_INSERT;\r
-          break;\r
-        case '-':\r
-          Key.ScanCode = SCAN_DELETE;\r
-          break;\r
-        case '/':\r
-          Key.ScanCode = SCAN_PAGE_DOWN;\r
-          break;\r
-        case '?':\r
-          Key.ScanCode = SCAN_PAGE_UP;\r
-          break;\r
-        default :\r
-          break;\r
-        }\r
-      }\r
-\r
-      switch (UnicodeChar) {\r
-      case 'R':\r
-        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
-          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
-          SetDefaultResetState = FALSE;\r
-        }\r
-        Key.ScanCode = SCAN_NULL;\r
-        break;\r
-      default :\r
-        break;\r
-      }\r
-\r
-      if (SetDefaultResetState) {\r
-        TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-      }\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
-\r
-      break;\r
-\r
-    case INPUT_STATE_ESC | INPUT_STATE_O:\r
-\r
-      TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-\r
-      Key.ScanCode = SCAN_NULL;\r
-\r
-      if (TerminalDevice->TerminalType == VT100TYPE) {\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 'w':\r
-          Key.ScanCode = SCAN_F3;\r
-          break;\r
-        case 'x':\r
-          Key.ScanCode = SCAN_F4;\r
-          break;\r
-        case 't':\r
-          Key.ScanCode = SCAN_F5;\r
-          break;\r
-        case 'u':\r
-          Key.ScanCode = SCAN_F6;\r
-          break;\r
-        case 'q':\r
-          Key.ScanCode = SCAN_F7;\r
-          break;\r
-        case 'r':\r
-          Key.ScanCode = SCAN_F8;\r
-          break;\r
-        case 'p':\r
-          Key.ScanCode = SCAN_F9;\r
-          break;\r
-        case 'M':\r
-          Key.ScanCode = SCAN_F10;\r
-          break;\r
-        default :\r
-          break;\r
-        }\r
-      }\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
-\r
-      break;\r
-\r
-    case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:\r
-\r
-      TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-\r
-      Key.ScanCode = SCAN_NULL;\r
-\r
-      if (TerminalDevice->TerminalType == PCANSITYPE    ||\r
-          TerminalDevice->TerminalType == VT100TYPE     ||\r
-          TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
-          TerminalDevice->TerminalType == VTUTF8TYPE) {\r
-        switch (UnicodeChar) {\r
-        case 'A':\r
-          Key.ScanCode = SCAN_UP;\r
-          break;\r
-        case 'B':\r
-          Key.ScanCode = SCAN_DOWN;\r
-          break;\r
-        case 'C':\r
-          Key.ScanCode = SCAN_RIGHT;\r
-          break;\r
-        case 'D':\r
-          Key.ScanCode = SCAN_LEFT;\r
-          break;\r
-        case 'H':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE ||\r
-              TerminalDevice->TerminalType == VT100TYPE) {\r
-            Key.ScanCode = SCAN_HOME;\r
-          }\r
-          break;\r
-        case 'F':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_END;\r
-          }\r
-          break;\r
-        case 'K':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
-            Key.ScanCode = SCAN_END;\r
-          }\r
-          break;\r
-        case 'L':\r
-        case '@':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE ||\r
-              TerminalDevice->TerminalType == VT100TYPE) {\r
-            Key.ScanCode = SCAN_INSERT;\r
-          }\r
-          break;\r
-        case 'X':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_DELETE;\r
-          }\r
-          break;\r
-        case 'P':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
-            Key.ScanCode = SCAN_DELETE;\r
-          } else if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F4;\r
-          }\r
-          break;\r
-        case 'I':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_PAGE_UP;\r
-          }\r
-          break;\r
-        case 'V':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F10;\r
-          }\r
-        case '?':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
-            Key.ScanCode = SCAN_PAGE_UP;\r
-          }\r
-          break;\r
-        case 'G':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_PAGE_DOWN;\r
-          }\r
-          break;\r
-        case 'U':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F9;\r
-          }\r
-        case '/':\r
-          if (TerminalDevice->TerminalType == VT100TYPE) {\r
-            Key.ScanCode = SCAN_PAGE_DOWN;\r
-          }\r
-          break;\r
-        case 'M':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F1;\r
-          }\r
-          break;\r
-        case 'N':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F2;\r
-          }\r
-          break;\r
-        case 'O':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F3;\r
-          }\r
-          break;\r
-        case 'Q':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F5;\r
-          }\r
-          break;\r
-        case 'R':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F6;\r
-          }\r
-          break;\r
-        case 'S':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F7;\r
-          }\r
-          break;\r
-        case 'T':\r
-          if (TerminalDevice->TerminalType == PCANSITYPE) {\r
-            Key.ScanCode = SCAN_F8;\r
-          }\r
-          break;\r
-        default :\r
-          break;\r
-        }\r
-      }\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
-\r
-      break;\r
-\r
-\r
-    default:\r
-      //\r
-      // Invalid state. This should never happen.\r
-      //\r
-      ASSERT (FALSE);\r
-\r
-      UnicodeToEfiKeyFlushState (TerminalDevice);\r
-\r
-      break;\r
-    }\r
-\r
-    if (UnicodeChar == ESC) {\r
-      TerminalDevice->InputState = INPUT_STATE_ESC;\r
-    }\r
-\r
-    if (UnicodeChar == CSI) {\r
-      TerminalDevice->InputState = INPUT_STATE_CSI;\r
-    }\r
-\r
-    if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
-      Status = gBS->SetTimer(\r
-                      TerminalDevice->TwoSecondTimeOut,\r
-                      TimerRelative,\r
-                      (UINT64)20000000\r
-                      );\r
-      ASSERT_EFI_ERROR (Status);\r
-      continue;\r
-    }\r
-\r
-    if (SetDefaultResetState) {\r
-      TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
-    }\r
-\r
-    if (UnicodeChar == DEL) {\r
-      Key.ScanCode    = SCAN_DELETE;\r
-      Key.UnicodeChar = 0;\r
-    } else {\r
-      Key.ScanCode    = SCAN_NULL;\r
-      Key.UnicodeChar = UnicodeChar;\r
-    }\r
-\r
-    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
-  }\r
-}\r
+/** @file
+  Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Terminal.h"
+
+
+/**
+  Reads the next keystroke from the input device. The WaitForKey Event can
+  be used to test for existence of a keystroke via WaitForEvent () call.
+
+  @param  TerminalDevice           Terminal driver private structure
+  @param  KeyData                  A pointer to a buffer that is filled in with the
+                                   keystroke state data for the key that was
+                                   pressed.
+
+  @retval EFI_SUCCESS              The keystroke information was returned.
+  @retval EFI_NOT_READY            There was no keystroke data available.
+  @retval EFI_INVALID_PARAMETER    KeyData is NULL.
+
+**/
+EFI_STATUS
+ReadKeyStrokeWorker (
+  IN  TERMINAL_DEV *TerminalDevice,
+  OUT EFI_KEY_DATA *KeyData
+  )
+{
+  if (KeyData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {
+    return EFI_NOT_READY;
+  }
+
+  KeyData->KeyState.KeyShiftState  = 0;
+  KeyData->KeyState.KeyToggleState = 0;
+
+
+  return EFI_SUCCESS;
+
+}
+
+/**
+  Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
+  This driver only perform dependent serial device reset regardless of
+  the value of ExtendeVerification
+
+  @param  This                     Indicates the calling context.
+  @param  ExtendedVerification     Skip by this driver.
+
+  @retval EFI_SUCCESS              The reset operation succeeds.
+  @retval EFI_DEVICE_ERROR         The dependent serial port reset fails.
+
+**/
+EFI_STATUS
+EFIAPI
+TerminalConInReset (
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
+  IN  BOOLEAN                         ExtendedVerification
+  )
+{
+  EFI_STATUS    Status;
+  TERMINAL_DEV  *TerminalDevice;
+
+  TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
+
+  //
+  // Report progress code here
+  //
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),
+    TerminalDevice->DevicePath
+    );
+
+  Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
+
+  //
+  // Make all the internal buffer empty for keys
+  //
+  TerminalDevice->RawFiFo->Head     = TerminalDevice->RawFiFo->Tail;
+  TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail;
+  TerminalDevice->EfiKeyFiFo->Head  = TerminalDevice->EfiKeyFiFo->Tail;
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),
+      TerminalDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
+
+  @param  This                Indicates the calling context.
+  @param  Key                 A pointer to a buffer that is filled in with the
+                              keystroke information for the key that was sent
+                              from terminal.
+
+  @retval EFI_SUCCESS         The keystroke information is returned successfully.
+  @retval EFI_NOT_READY       There is no keystroke data available.
+  @retval EFI_DEVICE_ERROR    The dependent serial device encounters error.
+
+**/
+EFI_STATUS
+EFIAPI
+TerminalConInReadKeyStroke (
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
+  OUT EFI_INPUT_KEY                   *Key
+  )
+{
+  TERMINAL_DEV  *TerminalDevice;
+  EFI_STATUS    Status;
+  EFI_KEY_DATA  KeyData;
+
+  //
+  //  get TERMINAL_DEV from "This" parameter.
+  //
+  TerminalDevice  = TERMINAL_CON_IN_DEV_FROM_THIS (This);
+
+  Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
+
+  return EFI_SUCCESS;
+
+}
+
+/**
+  Check if the key already has been registered.
+
+  If both RegsiteredData and InputData is NULL, then ASSERT().
+
+  @param  RegsiteredData           A pointer to a buffer that is filled in with the
+                                   keystroke state data for the key that was
+                                   registered.
+  @param  InputData                A pointer to a buffer that is filled in with the
+                                   keystroke state data for the key that was
+                                   pressed.
+
+  @retval TRUE                     Key be pressed matches a registered key.
+  @retval FLASE                    Match failed.
+
+**/
+BOOLEAN
+IsKeyRegistered (
+  IN EFI_KEY_DATA  *RegsiteredData,
+  IN EFI_KEY_DATA  *InputData
+  )
+{
+  ASSERT (RegsiteredData != NULL && InputData != NULL);
+
+  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||
+      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+
+
+/**
+  Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
+  Signal the event if there is key available
+
+  @param  Event                    Indicates the event that invoke this function.
+  @param  Context                  Indicates the calling context.
+
+**/
+VOID
+EFIAPI
+TerminalConInWaitForKeyEx (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  TerminalConInWaitForKey (Event, Context);
+}
+
+//
+// Simple Text Input Ex protocol functions
+//
+
+/**
+  Reset the input device and optionally run diagnostics
+
+  @param  This                     Protocol instance pointer.
+  @param  ExtendedVerification     Driver may perform diagnostics on reset.
+
+  @retval EFI_SUCCESS              The device was reset.
+  @retval EFI_DEVICE_ERROR         The device is not functioning properly and could
+                                   not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+TerminalConInResetEx (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN BOOLEAN                            ExtendedVerification
+  )
+{
+  EFI_STATUS              Status;
+  TERMINAL_DEV            *TerminalDevice;
+
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
+
+  Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+
+}
+
+
+/**
+  Reads the next keystroke from the input device. The WaitForKey Event can
+  be used to test for existence of a keystroke via WaitForEvent () call.
+
+  @param  This                     Protocol instance pointer.
+  @param  KeyData                  A pointer to a buffer that is filled in with the
+                                   keystroke state data for the key that was
+                                   pressed.
+
+  @retval EFI_SUCCESS              The keystroke information was returned.
+  @retval EFI_NOT_READY            There was no keystroke data available.
+  @retval EFI_DEVICE_ERROR         The keystroke information was not returned due
+                                   to hardware errors.
+  @retval EFI_INVALID_PARAMETER    KeyData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TerminalConInReadKeyStrokeEx (
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+  OUT EFI_KEY_DATA                      *KeyData
+  )
+{
+  TERMINAL_DEV                    *TerminalDevice;
+
+  if (KeyData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
+
+  return ReadKeyStrokeWorker (TerminalDevice, KeyData);
+
+}
+
+
+/**
+  Set certain state for the input device.
+
+  @param  This                     Protocol instance pointer.
+  @param  KeyToggleState           A pointer to the EFI_KEY_TOGGLE_STATE to set the
+                                   state for the input device.
+
+  @retval EFI_SUCCESS              The device state was set successfully.
+  @retval EFI_DEVICE_ERROR         The device is not functioning correctly and
+                                   could not have the setting adjusted.
+  @retval EFI_UNSUPPORTED          The device does not have the ability to set its
+                                   state.
+  @retval EFI_INVALID_PARAMETER    KeyToggleState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TerminalConInSetState (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
+  )
+{
+  if (KeyToggleState == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Register a notification function for a particular keystroke for the input device.
+
+  @param  This                     Protocol instance pointer.
+  @param  KeyData                  A pointer to a buffer that is filled in with the
+                                   keystroke information data for the key that was
+                                   pressed.
+  @param  KeyNotificationFunction  Points to the function to be called when the key
+                                   sequence is typed specified by KeyData.
+  @param  NotifyHandle             Points to the unique handle assigned to the
+                                   registered notification.
+
+  @retval EFI_SUCCESS              The notification function was registered
+                                   successfully.
+  @retval EFI_OUT_OF_RESOURCES     Unable to allocate resources for necessary data
+                                   structures.
+  @retval EFI_INVALID_PARAMETER    KeyData or NotifyHandle is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TerminalConInRegisterKeyNotify (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN EFI_KEY_DATA                       *KeyData,
+  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
+  OUT EFI_HANDLE                        *NotifyHandle
+  )
+{
+  TERMINAL_DEV                    *TerminalDevice;
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *NewNotify;
+  LIST_ENTRY                      *Link;
+  LIST_ENTRY                      *NotifyList;
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;
+
+  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
+
+  //
+  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
+  //
+  NotifyList = &TerminalDevice->NotifyList;
+  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
+    CurrentNotify = CR (
+                      Link,
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY,
+                      NotifyEntry,
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+                      );
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
+      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
+        *NotifyHandle = CurrentNotify->NotifyHandle;
+        return EFI_SUCCESS;
+      }
+    }
+  }
+
+  //
+  // Allocate resource to save the notification function
+  //
+  NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));
+  if (NewNotify == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  NewNotify->Signature         = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
+  NewNotify->KeyNotificationFn = KeyNotificationFunction;
+  NewNotify->NotifyHandle      = (EFI_HANDLE) NewNotify;
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));
+  InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);
+
+  *NotifyHandle                = NewNotify->NotifyHandle;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Remove a registered notification function from a particular keystroke.
+
+  @param  This                     Protocol instance pointer.
+  @param  NotificationHandle       The handle of the notification function being
+                                   unregistered.
+
+  @retval EFI_SUCCESS              The notification function was unregistered
+                                   successfully.
+  @retval EFI_INVALID_PARAMETER    The NotificationHandle is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+TerminalConInUnregisterKeyNotify (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN EFI_HANDLE                         NotificationHandle
+  )
+{
+  TERMINAL_DEV                    *TerminalDevice;
+  LIST_ENTRY                      *Link;
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;
+  LIST_ENTRY                      *NotifyList;
+
+  if (NotificationHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((TERMINAL_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {
+    return EFI_INVALID_PARAMETER;
+  } 
+  
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
+
+  NotifyList = &TerminalDevice->NotifyList;
+  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
+    CurrentNotify = CR (
+                      Link,
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY,
+                      NotifyEntry,
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+                      );
+    if (CurrentNotify->NotifyHandle == NotificationHandle) {
+      //
+      // Remove the notification function from NotifyList and free resources
+      //
+      RemoveEntryList (&CurrentNotify->NotifyEntry);
+
+      gBS->FreePool (CurrentNotify);
+      return EFI_SUCCESS;
+    }
+  }
+
+  //
+  // Can not find the matching entry in database.
+  //
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Translate raw data into Unicode (according to different encode), and
+  translate Unicode into key information. (according to different standard).
+
+  @param  TerminalDevice       Terminal driver private structure.
+
+**/
+VOID
+TranslateRawDataToEfiKey (
+  IN  TERMINAL_DEV      *TerminalDevice
+  )
+{
+  switch (TerminalDevice->TerminalType) {
+
+  case PCANSITYPE:
+  case VT100TYPE:
+  case VT100PLUSTYPE:
+    AnsiRawDataToUnicode (TerminalDevice);
+    UnicodeToEfiKey (TerminalDevice);
+    break;
+
+  case VTUTF8TYPE:
+    //
+    // Process all the raw data in the RawFIFO,
+    // put the processed key into UnicodeFIFO.
+    //
+    VTUTF8RawDataToUnicode (TerminalDevice);
+
+    //
+    // Translate all the Unicode data in the UnicodeFIFO to Efi key,
+    // then put into EfiKeyFIFO.
+    //
+    UnicodeToEfiKey (TerminalDevice);
+
+    break;
+  }
+}
+
+/**
+  Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
+  Signal the event if there is key available
+
+  @param  Event                    Indicates the event that invoke this function.
+  @param  Context                  Indicates the calling context.
+
+**/
+VOID
+EFIAPI
+TerminalConInWaitForKey (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  //
+  // Someone is waiting on the keystroke event, if there's
+  // a key pending, signal the event
+  //
+  if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) {
+
+    gBS->SignalEvent (Event);
+  }
+}
+
+/**
+  Timer handler to poll the key from serial.
+
+  @param  Event                    Indicates the event that invoke this function.
+  @param  Context                  Indicates the calling context.
+**/
+VOID
+EFIAPI
+TerminalConInTimerHandler (
+  IN EFI_EVENT            Event,
+  IN VOID                 *Context
+  )
+{
+  EFI_STATUS              Status;
+  TERMINAL_DEV            *TerminalDevice;
+  UINT8                   Input;
+  EFI_SERIAL_IO_MODE      *Mode;
+  EFI_SERIAL_IO_PROTOCOL  *SerialIo;
+  UINTN                   SerialInTimeOut;
+
+  TerminalDevice  = (TERMINAL_DEV *) Context;
+
+  SerialIo        = TerminalDevice->SerialIo;
+  if (SerialIo == NULL) {
+    return ;
+  }
+  //
+  //  if current timeout value for serial device is not identical with
+  //  the value saved in TERMINAL_DEV structure, then recalculate the
+  //  timeout value again and set serial attribute according to this value.
+  //
+  Mode = SerialIo->Mode;
+  if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {
+
+    SerialInTimeOut = 0;
+    if (Mode->BaudRate != 0) {
+      //
+      // According to BAUD rate to calculate the timeout value.
+      //
+      SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;
+    }
+
+    Status = SerialIo->SetAttributes (
+                        SerialIo,
+                        Mode->BaudRate,
+                        Mode->ReceiveFifoDepth,
+                        (UINT32) SerialInTimeOut,
+                        (EFI_PARITY_TYPE) (Mode->Parity),
+                        (UINT8) Mode->DataBits,
+                        (EFI_STOP_BITS_TYPE) (Mode->StopBits)
+                        );
+
+    if (EFI_ERROR (Status)) {
+      TerminalDevice->SerialInTimeOut = 0;
+    } else {
+      TerminalDevice->SerialInTimeOut = SerialInTimeOut;
+    }
+  }
+
+  //
+  // Fetch all the keys in the serial buffer,
+  // and insert the byte stream into RawFIFO.
+  //
+  while( !IsRawFiFoFull(TerminalDevice) ) {
+
+    Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);
+
+    if (EFI_ERROR (Status)) {
+      if (Status == EFI_DEVICE_ERROR) {
+        REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+          EFI_ERROR_CODE | EFI_ERROR_MINOR,
+          (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR),
+          TerminalDevice->DevicePath
+          );
+      }
+      break;
+    }
+
+    RawFiFoInsertOneKey (TerminalDevice, Input);
+  }
+
+  //
+  // Translate all the raw data in RawFIFO into EFI Key,
+  // according to different terminal type supported.
+  //
+  TranslateRawDataToEfiKey (TerminalDevice);
+}
+
+/**
+  Get one key out of serial buffer.
+
+  @param  SerialIo           Serial I/O protocol attached to the serial device.
+  @param  Output             The fetched key.
+
+  @retval EFI_NOT_READY      If serial buffer is empty.
+  @retval EFI_DEVICE_ERROR   If reading serial buffer encounter error.
+  @retval EFI_SUCCESS        If reading serial buffer successfully, put
+                             the fetched key to the parameter output.
+
+**/
+EFI_STATUS
+GetOneKeyFromSerial (
+  EFI_SERIAL_IO_PROTOCOL  *SerialIo,
+  UINT8                   *Output
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Size;
+
+  Size    = 1;
+  *Output = 0;
+
+  //
+  // Read one key from serial I/O device.
+  //
+  Status  = SerialIo->Read (SerialIo, &Size, Output);
+
+  if (EFI_ERROR (Status)) {
+
+    if (Status == EFI_TIMEOUT) {
+      return EFI_NOT_READY;
+    }
+
+    return EFI_DEVICE_ERROR;
+
+  }
+
+  if (*Output == 0) {
+    return EFI_NOT_READY;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Insert one byte raw data into the Raw Data FIFO.
+
+  @param  TerminalDevice       Terminal driver private structure.
+  @param  Input                The key will be input.
+
+  @retval TRUE                 If insert successfully.
+  @retval FLASE                If Raw Data buffer is full before key insertion,
+                               and the key is lost.
+
+**/
+BOOLEAN
+RawFiFoInsertOneKey (
+  TERMINAL_DEV      *TerminalDevice,
+  UINT8             Input
+  )
+{
+  UINT8 Tail;
+
+  Tail = TerminalDevice->RawFiFo->Tail;
+
+  if (IsRawFiFoFull (TerminalDevice)) {
+    //
+    // Raw FIFO is full
+    //
+    return FALSE;
+  }
+
+  TerminalDevice->RawFiFo->Data[Tail]  = Input;
+
+  TerminalDevice->RawFiFo->Tail        = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Remove one pre-fetched key out of the Raw Data FIFO.
+
+  @param  TerminalDevice       Terminal driver private structure.
+  @param  Output               The key will be removed.
+
+  @retval TRUE                 If insert successfully.
+  @retval FLASE                If Raw Data FIFO buffer is empty before remove operation.
+
+**/
+BOOLEAN
+RawFiFoRemoveOneKey (
+  TERMINAL_DEV  *TerminalDevice,
+  UINT8         *Output
+  )
+{
+  UINT8 Head;
+
+  Head = TerminalDevice->RawFiFo->Head;
+
+  if (IsRawFiFoEmpty (TerminalDevice)) {
+    //
+    //  FIFO is empty
+    //
+    *Output = 0;
+    return FALSE;
+  }
+
+  *Output                       = TerminalDevice->RawFiFo->Data[Head];
+
+  TerminalDevice->RawFiFo->Head  = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Clarify whether Raw Data FIFO buffer is empty.
+
+  @param  TerminalDevice       Terminal driver private structure
+
+  @retval TRUE                 If Raw Data FIFO buffer is empty.
+  @retval FLASE                If Raw Data FIFO buffer is not empty.
+
+**/
+BOOLEAN
+IsRawFiFoEmpty (
+  TERMINAL_DEV  *TerminalDevice
+  )
+{
+  if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Clarify whether Raw Data FIFO buffer is full.
+
+  @param  TerminalDevice       Terminal driver private structure
+
+  @retval TRUE                 If Raw Data FIFO buffer is full.
+  @retval FLASE                If Raw Data FIFO buffer is not full.
+
+**/
+BOOLEAN
+IsRawFiFoFull (
+  TERMINAL_DEV  *TerminalDevice
+  )
+{
+  UINT8 Tail;
+  UINT8 Head;
+
+  Tail  = TerminalDevice->RawFiFo->Tail;
+  Head  = TerminalDevice->RawFiFo->Head;
+
+  if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Insert one pre-fetched key into the FIFO buffer.
+
+  @param  TerminalDevice       Terminal driver private structure.
+  @param  Key                  The key will be input.
+
+  @retval TRUE                 If insert successfully.
+  @retval FLASE                If FIFO buffer is full before key insertion,
+                               and the key is lost.
+
+**/
+BOOLEAN
+EfiKeyFiFoInsertOneKey (
+  TERMINAL_DEV                    *TerminalDevice,
+  EFI_INPUT_KEY                   *Key
+  )
+{
+  UINT8                           Tail;
+  LIST_ENTRY                      *Link;
+  LIST_ENTRY                      *NotifyList;
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;
+  EFI_KEY_DATA                    KeyData;
+
+  Tail = TerminalDevice->EfiKeyFiFo->Tail;
+
+  CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));
+  KeyData.KeyState.KeyShiftState  = 0;
+  KeyData.KeyState.KeyToggleState = 0;
+
+  //
+  // Invoke notification functions if exist
+  //
+  NotifyList = &TerminalDevice->NotifyList;
+  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
+    CurrentNotify = CR (
+                      Link,
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY,
+                      NotifyEntry,
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+                      );
+    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+      CurrentNotify->KeyNotificationFn (&KeyData);
+    }
+  }
+  if (IsEfiKeyFiFoFull (TerminalDevice)) {
+    //
+    // Efi Key FIFO is full
+    //
+    return FALSE;
+  }
+
+  CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));
+
+  TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Remove one pre-fetched key out of the FIFO buffer.
+
+  @param  TerminalDevice       Terminal driver private structure.
+  @param  Output               The key will be removed.
+
+  @retval TRUE                 If insert successfully.
+  @retval FLASE                If FIFO buffer is empty before remove operation.
+
+**/
+BOOLEAN
+EfiKeyFiFoRemoveOneKey (
+  TERMINAL_DEV  *TerminalDevice,
+  EFI_INPUT_KEY *Output
+  )
+{
+  UINT8 Head;
+
+  Head = TerminalDevice->EfiKeyFiFo->Head;
+  ASSERT (Head < FIFO_MAX_NUMBER + 1);
+
+  if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
+    //
+    //  FIFO is empty
+    //
+    Output->ScanCode    = SCAN_NULL;
+    Output->UnicodeChar = 0;
+    return FALSE;
+  }
+
+  *Output                         = TerminalDevice->EfiKeyFiFo->Data[Head];
+
+  TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Clarify whether FIFO buffer is empty.
+
+  @param  TerminalDevice       Terminal driver private structure
+
+  @retval TRUE                 If FIFO buffer is empty.
+  @retval FLASE                If FIFO buffer is not empty.
+
+**/
+BOOLEAN
+IsEfiKeyFiFoEmpty (
+  TERMINAL_DEV  *TerminalDevice
+  )
+{
+  if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Clarify whether FIFO buffer is full.
+
+  @param  TerminalDevice       Terminal driver private structure
+
+  @retval TRUE                 If FIFO buffer is full.
+  @retval FLASE                If FIFO buffer is not full.
+
+**/
+BOOLEAN
+IsEfiKeyFiFoFull (
+  TERMINAL_DEV  *TerminalDevice
+  )
+{
+  UINT8 Tail;
+  UINT8 Head;
+
+  Tail  = TerminalDevice->EfiKeyFiFo->Tail;
+  Head  = TerminalDevice->EfiKeyFiFo->Head;
+
+  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Insert one pre-fetched key into the Unicode FIFO buffer.
+
+  @param  TerminalDevice       Terminal driver private structure.
+  @param  Input                The key will be input.
+
+  @retval TRUE                 If insert successfully.
+  @retval FLASE                If Unicode FIFO buffer is full before key insertion,
+                               and the key is lost.
+
+**/
+BOOLEAN
+UnicodeFiFoInsertOneKey (
+  TERMINAL_DEV      *TerminalDevice,
+  UINT16            Input
+  )
+{
+  UINT8 Tail;
+
+  Tail = TerminalDevice->UnicodeFiFo->Tail;
+  ASSERT (Tail < FIFO_MAX_NUMBER + 1);
+
+
+  if (IsUnicodeFiFoFull (TerminalDevice)) {
+    //
+    // Unicode FIFO is full
+    //
+    return FALSE;
+  }
+
+  TerminalDevice->UnicodeFiFo->Data[Tail]  = Input;
+
+  TerminalDevice->UnicodeFiFo->Tail        = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Remove one pre-fetched key out of the Unicode FIFO buffer.
+
+  @param  TerminalDevice       Terminal driver private structure.
+  @param  Output               The key will be removed.
+
+  @retval TRUE                 If insert successfully.
+  @retval FLASE                If Unicode FIFO buffer is empty before remove operation.
+
+**/
+BOOLEAN
+UnicodeFiFoRemoveOneKey (
+  TERMINAL_DEV  *TerminalDevice,
+  UINT16        *Output
+  )
+{
+  UINT8 Head;
+
+  Head = TerminalDevice->UnicodeFiFo->Head;
+  ASSERT (Head < FIFO_MAX_NUMBER + 1);
+
+  if (IsUnicodeFiFoEmpty (TerminalDevice)) {
+    //
+    //  FIFO is empty
+    //
+    Output = NULL;
+    return FALSE;
+  }
+
+  *Output = TerminalDevice->UnicodeFiFo->Data[Head];
+
+  TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Clarify whether Unicode FIFO buffer is empty.
+
+  @param  TerminalDevice       Terminal driver private structure
+
+  @retval TRUE                 If Unicode FIFO buffer is empty.
+  @retval FLASE                If Unicode FIFO buffer is not empty.
+
+**/
+BOOLEAN
+IsUnicodeFiFoEmpty (
+  TERMINAL_DEV  *TerminalDevice
+  )
+{
+  if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Clarify whether Unicode FIFO buffer is full.
+
+  @param  TerminalDevice       Terminal driver private structure
+
+  @retval TRUE                 If Unicode FIFO buffer is full.
+  @retval FLASE                If Unicode FIFO buffer is not full.
+
+**/
+BOOLEAN
+IsUnicodeFiFoFull (
+  TERMINAL_DEV  *TerminalDevice
+  )
+{
+  UINT8 Tail;
+  UINT8 Head;
+
+  Tail  = TerminalDevice->UnicodeFiFo->Tail;
+  Head  = TerminalDevice->UnicodeFiFo->Head;
+
+  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Count Unicode FIFO buffer.
+
+  @param  TerminalDevice       Terminal driver private structure
+
+  @return The count in bytes of Unicode FIFO.
+
+**/
+UINT8
+UnicodeFiFoGetKeyCount (
+  TERMINAL_DEV    *TerminalDevice
+  )
+{
+  UINT8 Tail;
+  UINT8 Head;
+
+  Tail  = TerminalDevice->UnicodeFiFo->Tail;
+  Head  = TerminalDevice->UnicodeFiFo->Head;
+
+  if (Tail >= Head) {
+    return (UINT8) (Tail - Head);
+  } else {
+    return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);
+  }
+}
+
+/**
+  Update the Unicode characters from a terminal input device into EFI Keys FIFO.
+
+  @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys
+
+**/
+VOID
+UnicodeToEfiKeyFlushState (
+  IN  TERMINAL_DEV    *TerminalDevice
+  )
+{
+  EFI_INPUT_KEY Key;
+  UINT32        InputState;
+
+  InputState = TerminalDevice->InputState;
+
+  if( IsEfiKeyFiFoFull(TerminalDevice) ) return;
+
+  if ((InputState & INPUT_STATE_ESC) != 0) {
+    Key.ScanCode    = SCAN_ESC;
+    Key.UnicodeChar = 0;
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+  }
+
+  if ((InputState & INPUT_STATE_CSI) != 0) {
+    Key.ScanCode    = SCAN_NULL;
+    Key.UnicodeChar = CSI;
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+  }
+
+  if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {
+    Key.ScanCode    = SCAN_NULL;
+    Key.UnicodeChar = LEFTOPENBRACKET;
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+  }
+
+  if ((InputState & INPUT_STATE_O) != 0) {
+    Key.ScanCode    = SCAN_NULL;
+    Key.UnicodeChar = 'O';
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+  }
+
+  if ((InputState & INPUT_STATE_2) != 0) {
+    Key.ScanCode    = SCAN_NULL;
+    Key.UnicodeChar = '2';
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+  }
+
+  //
+  // Cancel the timer.
+  //
+  gBS->SetTimer (
+        TerminalDevice->TwoSecondTimeOut,
+        TimerCancel,
+        0
+        );
+
+  TerminalDevice->InputState = INPUT_STATE_DEFAULT;
+}
+
+
+/**
+  Converts a stream of Unicode characters from a terminal input device into EFI Keys that
+  can be read through the Simple Input Protocol.
+
+  The table below shows the keyboard input mappings that this function supports.
+  If the ESC sequence listed in one of the columns is presented, then it is translated
+  into the corresponding EFI Scan Code.  If a matching sequence is not found, then the raw
+  key strokes are converted into EFI Keys.
+
+  2 seconds are allowed for an ESC sequence to be completed.  If the ESC sequence is not
+  completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
+  converted into EFI Keys.
+  There is one special input sequence that will force the system to reset.
+  This is ESC R ESC r ESC R.
+
+  Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100. 
+        The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
+        DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
+        
+  Symbols used in table below
+  ===========================
+    ESC = 0x1B
+    CSI = 0x9B
+    DEL = 0x7f
+    ^   = CTRL
+
+  +=========+======+===========+==========+==========+
+  |         | EFI  | UEFI 2.0  |          |          |
+  |         | Scan |           |  VT100+  |          |
+  |   KEY   | Code |  PC ANSI  |  VTUTF8  |   VT100  |
+  +=========+======+===========+==========+==========+
+  | NULL    | 0x00 |           |          |          |
+  | UP      | 0x01 | ESC [ A   | ESC [ A  | ESC [ A  |
+  | DOWN    | 0x02 | ESC [ B   | ESC [ B  | ESC [ B  |
+  | RIGHT   | 0x03 | ESC [ C   | ESC [ C  | ESC [ C  |
+  | LEFT    | 0x04 | ESC [ D   | ESC [ D  | ESC [ D  |
+  | HOME    | 0x05 | ESC [ H   | ESC h    | ESC [ H  |
+  | END     | 0x06 | ESC [ F   | ESC k    | ESC [ K  |
+  | INSERT  | 0x07 | ESC [ @   | ESC +    | ESC [ @  |
+  |         |      | ESC [ L   |          | ESC [ L  |
+  | DELETE  | 0x08 | ESC [ X   | ESC -    | ESC [ P  |
+  | PG UP   | 0x09 | ESC [ I   | ESC ?    | ESC [ V  |
+  |         |      |           |          | ESC [ ?  |
+  | PG DOWN | 0x0A | ESC [ G   | ESC /    | ESC [ U  |
+  |         |      |           |          | ESC [ /  |
+  | F1      | 0x0B | ESC [ M   | ESC 1    | ESC O P  |
+  | F2      | 0x0C | ESC [ N   | ESC 2    | ESC O Q  |
+  | F3      | 0x0D | ESC [ O   | ESC 3    | ESC O w  |
+  | F4      | 0x0E | ESC [ P   | ESC 4    | ESC O x  |
+  | F5      | 0x0F | ESC [ Q   | ESC 5    | ESC O t  |
+  | F6      | 0x10 | ESC [ R   | ESC 6    | ESC O u  |
+  | F7      | 0x11 | ESC [ S   | ESC 7    | ESC O q  |
+  | F8      | 0x12 | ESC [ T   | ESC 8    | ESC O r  |
+  | F9      | 0x13 | ESC [ U   | ESC 9    | ESC O p  |
+  | F10     | 0x14 | ESC [ V   | ESC 0    | ESC O M  |
+  | Escape  | 0x17 | ESC       | ESC      | ESC      |
+  | F11     | 0x15 |           | ESC !    |          |
+  | F12     | 0x16 |           | ESC @    |          |
+  +=========+======+===========+==========+==========+
+
+  Special Mappings
+  ================
+  ESC R ESC r ESC R = Reset System
+
+  @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys
+
+**/
+VOID
+UnicodeToEfiKey (
+  IN  TERMINAL_DEV    *TerminalDevice
+  )
+{
+  EFI_STATUS          Status;
+  EFI_STATUS          TimerStatus;
+  UINT16              UnicodeChar;
+  EFI_INPUT_KEY       Key;
+  BOOLEAN             SetDefaultResetState;
+
+  TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
+
+  if (!EFI_ERROR (TimerStatus)) {
+    UnicodeToEfiKeyFlushState (TerminalDevice);
+    TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+  }
+
+  while (!IsUnicodeFiFoEmpty(TerminalDevice) && !IsEfiKeyFiFoFull(TerminalDevice) ) {
+
+    if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
+      //
+      // Check to see if the 2 seconds timer has expired
+      //
+      TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
+      if (!EFI_ERROR (TimerStatus)) {
+        UnicodeToEfiKeyFlushState (TerminalDevice);
+        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+      }
+    }
+
+    //
+    // Fetch one Unicode character from the Unicode FIFO
+    //
+    UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);
+
+    SetDefaultResetState = TRUE;
+
+    switch (TerminalDevice->InputState) {
+    case INPUT_STATE_DEFAULT:
+
+      break;
+
+    case INPUT_STATE_ESC:
+
+      if (UnicodeChar == LEFTOPENBRACKET) {
+        TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
+        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+        continue;
+      }
+
+      if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {
+        TerminalDevice->InputState |= INPUT_STATE_O;
+        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+        continue;
+      }
+
+      Key.ScanCode = SCAN_NULL;
+
+      if (TerminalDevice->TerminalType == VT100PLUSTYPE ||
+          TerminalDevice->TerminalType == VTUTF8TYPE) {
+        switch (UnicodeChar) {
+        case '1':
+          Key.ScanCode = SCAN_F1;
+          break;
+        case '2':
+          Key.ScanCode = SCAN_F2;
+          break;
+        case '3':
+          Key.ScanCode = SCAN_F3;
+          break;
+        case '4':
+          Key.ScanCode = SCAN_F4;
+          break;
+        case '5':
+          Key.ScanCode = SCAN_F5;
+          break;
+        case '6':
+          Key.ScanCode = SCAN_F6;
+          break;
+        case '7':
+          Key.ScanCode = SCAN_F7;
+          break;
+        case '8':
+          Key.ScanCode = SCAN_F8;
+          break;
+        case '9':
+          Key.ScanCode = SCAN_F9;
+          break;
+        case '0':
+          Key.ScanCode = SCAN_F10;
+          break;
+        case '!':
+          Key.ScanCode = SCAN_F11;
+          break;
+        case '@':
+          Key.ScanCode = SCAN_F12;
+          break;
+        case 'h':
+          Key.ScanCode = SCAN_HOME;
+          break;
+        case 'k':
+          Key.ScanCode = SCAN_END;
+          break;
+        case '+':
+          Key.ScanCode = SCAN_INSERT;
+          break;
+        case '-':
+          Key.ScanCode = SCAN_DELETE;
+          break;
+        case '/':
+          Key.ScanCode = SCAN_PAGE_DOWN;
+          break;
+        case '?':
+          Key.ScanCode = SCAN_PAGE_UP;
+          break;
+        default :
+          break;
+        }
+      }
+
+      switch (UnicodeChar) {
+      case 'R':
+        if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
+          TerminalDevice->ResetState = RESET_STATE_ESC_R;
+          SetDefaultResetState = FALSE;
+        } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_R) {
+          gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+        }
+        Key.ScanCode = SCAN_NULL;
+        break;
+      case 'r':
+        if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
+          TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_R;
+          SetDefaultResetState = FALSE;
+        }
+        Key.ScanCode = SCAN_NULL;
+        break;
+      default :
+        break;
+      }
+
+      if (SetDefaultResetState) {
+        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+      }
+
+      if (Key.ScanCode != SCAN_NULL) {
+        Key.UnicodeChar = 0;
+        EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+        TerminalDevice->InputState = INPUT_STATE_DEFAULT;
+        UnicodeToEfiKeyFlushState (TerminalDevice);
+        continue;
+      }
+
+      UnicodeToEfiKeyFlushState (TerminalDevice);
+
+      break;
+
+    case INPUT_STATE_ESC | INPUT_STATE_O:
+
+      TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+
+      Key.ScanCode = SCAN_NULL;
+
+      if (TerminalDevice->TerminalType == VT100TYPE) {
+        switch (UnicodeChar) {
+        case 'P':
+          Key.ScanCode = SCAN_F1;
+          break;
+        case 'Q':
+          Key.ScanCode = SCAN_F2;
+          break;
+        case 'w':
+          Key.ScanCode = SCAN_F3;
+          break;
+        case 'x':
+          Key.ScanCode = SCAN_F4;
+          break;
+        case 't':
+          Key.ScanCode = SCAN_F5;
+          break;
+        case 'u':
+          Key.ScanCode = SCAN_F6;
+          break;
+        case 'q':
+          Key.ScanCode = SCAN_F7;
+          break;
+        case 'r':
+          Key.ScanCode = SCAN_F8;
+          break;
+        case 'p':
+          Key.ScanCode = SCAN_F9;
+          break;
+        case 'M':
+          Key.ScanCode = SCAN_F10;
+          break;
+        default :
+          break;
+        }
+      }
+
+      if (Key.ScanCode != SCAN_NULL) {
+        Key.UnicodeChar = 0;
+        EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+        TerminalDevice->InputState = INPUT_STATE_DEFAULT;
+        UnicodeToEfiKeyFlushState (TerminalDevice);
+        continue;
+      }
+
+      UnicodeToEfiKeyFlushState (TerminalDevice);
+
+      break;
+
+    case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
+
+      TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+
+      Key.ScanCode = SCAN_NULL;
+
+      if (TerminalDevice->TerminalType == PCANSITYPE    ||
+          TerminalDevice->TerminalType == VT100TYPE     ||
+          TerminalDevice->TerminalType == VT100PLUSTYPE ||
+          TerminalDevice->TerminalType == VTUTF8TYPE) {
+        switch (UnicodeChar) {
+        case 'A':
+          Key.ScanCode = SCAN_UP;
+          break;
+        case 'B':
+          Key.ScanCode = SCAN_DOWN;
+          break;
+        case 'C':
+          Key.ScanCode = SCAN_RIGHT;
+          break;
+        case 'D':
+          Key.ScanCode = SCAN_LEFT;
+          break;
+        case 'H':
+          if (TerminalDevice->TerminalType == PCANSITYPE ||
+              TerminalDevice->TerminalType == VT100TYPE) {
+            Key.ScanCode = SCAN_HOME;
+          }
+          break;
+        case 'F':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_END;
+          }
+          break;
+        case 'K':
+          if (TerminalDevice->TerminalType == VT100TYPE) {
+            Key.ScanCode = SCAN_END;
+          }
+          break;
+        case 'L':
+        case '@':
+          if (TerminalDevice->TerminalType == PCANSITYPE ||
+              TerminalDevice->TerminalType == VT100TYPE) {
+            Key.ScanCode = SCAN_INSERT;
+          }
+          break;
+        case 'X':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_DELETE;
+          }
+          break;
+        case 'P':
+          if (TerminalDevice->TerminalType == VT100TYPE) {
+            Key.ScanCode = SCAN_DELETE;
+          } else if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F4;
+          }
+          break;
+        case 'I':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_PAGE_UP;
+          }
+          break;
+        case 'V':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F10;
+          }
+        case '?':
+          if (TerminalDevice->TerminalType == VT100TYPE) {
+            Key.ScanCode = SCAN_PAGE_UP;
+          }
+          break;
+        case 'G':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_PAGE_DOWN;
+          }
+          break;
+        case 'U':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F9;
+          }
+        case '/':
+          if (TerminalDevice->TerminalType == VT100TYPE) {
+            Key.ScanCode = SCAN_PAGE_DOWN;
+          }
+          break;
+        case 'M':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F1;
+          }
+          break;
+        case 'N':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F2;
+          }
+          break;
+        case 'O':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F3;
+          }
+          break;
+        case 'Q':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F5;
+          }
+          break;
+        case 'R':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F6;
+          }
+          break;
+        case 'S':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F7;
+          }
+          break;
+        case 'T':
+          if (TerminalDevice->TerminalType == PCANSITYPE) {
+            Key.ScanCode = SCAN_F8;
+          }
+          break;
+        default :
+          break;
+        }
+      }
+
+      if (Key.ScanCode != SCAN_NULL) {
+        Key.UnicodeChar = 0;
+        EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+        TerminalDevice->InputState = INPUT_STATE_DEFAULT;
+        UnicodeToEfiKeyFlushState (TerminalDevice);
+        continue;
+      }
+
+      UnicodeToEfiKeyFlushState (TerminalDevice);
+
+      break;
+
+
+    default:
+      //
+      // Invalid state. This should never happen.
+      //
+      ASSERT (FALSE);
+
+      UnicodeToEfiKeyFlushState (TerminalDevice);
+
+      break;
+    }
+
+    if (UnicodeChar == ESC) {
+      TerminalDevice->InputState = INPUT_STATE_ESC;
+    }
+
+    if (UnicodeChar == CSI) {
+      TerminalDevice->InputState = INPUT_STATE_CSI;
+    }
+
+    if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
+      Status = gBS->SetTimer(
+                      TerminalDevice->TwoSecondTimeOut,
+                      TimerRelative,
+                      (UINT64)20000000
+                      );
+      ASSERT_EFI_ERROR (Status);
+      continue;
+    }
+
+    if (SetDefaultResetState) {
+      TerminalDevice->ResetState = RESET_STATE_DEFAULT;
+    }
+
+    if (UnicodeChar == DEL) {
+      Key.ScanCode    = SCAN_DELETE;
+      Key.UnicodeChar = 0;
+    } else {
+      Key.ScanCode    = SCAN_NULL;
+      Key.UnicodeChar = UnicodeChar;
+    }
+
+    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
+  }
+}
index 26fc13147a040aaf255dda636f3c145aac73da20..1ad2f9c6b8f5257daddf599c93a4b4d89138fe01 100644 (file)
-/** @file\r
-  Implementation of translation upon VT-UTF8.\r
-\r
-Copyright (c) 2006 - 2010, 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
-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
-\r
-**/\r
-\r
-#include "Terminal.h"\r
-\r
-/**\r
-  Translate all VT-UTF8 characters in the Raw FIFI into unicode characters,\r
-  and insert them into Unicode FIFO.\r
-\r
-  @param TerminalDevice          The terminal device.\r
-\r
-**/\r
-VOID\r
-VTUTF8RawDataToUnicode (\r
-  IN  TERMINAL_DEV    *TerminalDevice\r
-  )\r
-{\r
-  UTF8_CHAR Utf8Char;\r
-  UINT8     ValidBytes;\r
-  UINT16    UnicodeChar;\r
-\r
-  ValidBytes = 0;\r
-  //\r
-  // pop the raw data out from the raw fifo,\r
-  // and translate it into unicode, then push\r
-  // the unicode into unicode fifo, until the raw fifo is empty.\r
-  //\r
-  while (!IsRawFiFoEmpty (TerminalDevice)) {\r
-\r
-    GetOneValidUtf8Char (TerminalDevice, &Utf8Char, &ValidBytes);\r
-\r
-    if (ValidBytes < 1 || ValidBytes > 3) {\r
-      continue;\r
-    }\r
-\r
-    Utf8ToUnicode (Utf8Char, ValidBytes, (CHAR16 *) &UnicodeChar);\r
-\r
-    UnicodeFiFoInsertOneKey (TerminalDevice, UnicodeChar);\r
-  }\r
-}\r
-\r
-/**\r
-  Get one valid VT-UTF8 characters set from Raw Data FIFO.\r
-\r
-  @param  Utf8Device          The terminal device.\r
-  @param  Utf8Char            Returned valid VT-UTF8 characters set.\r
-  @param  ValidBytes          The count of returned VT-VTF8 characters.\r
-                              If ValidBytes is zero, no valid VT-UTF8 returned.\r
-\r
-**/\r
-VOID\r
-GetOneValidUtf8Char (\r
-  IN  TERMINAL_DEV      *Utf8Device,\r
-  OUT UTF8_CHAR         *Utf8Char,\r
-  OUT UINT8             *ValidBytes\r
-  )\r
-{\r
-  UINT8   Temp;\r
-  UINT8   Index;\r
-  BOOLEAN FetchFlag;\r
-\r
-  Temp      = 0;\r
-  Index     = 0;\r
-  FetchFlag = TRUE;\r
-\r
-  //\r
-  // if no valid Utf8 char is found in the RawFiFo,\r
-  // then *ValidBytes will be zero.\r
-  //\r
-  *ValidBytes = 0;\r
-\r
-  while (!IsRawFiFoEmpty (Utf8Device)) {\r
-\r
-    RawFiFoRemoveOneKey (Utf8Device, &Temp);\r
-\r
-    switch (*ValidBytes) {\r
-\r
-    case 0:\r
-      if ((Temp & 0x80) == 0) {\r
-        //\r
-        // one-byte utf8 char\r
-        //\r
-        *ValidBytes       = 1;\r
-\r
-        Utf8Char->Utf8_1  = Temp;\r
-\r
-        FetchFlag         = FALSE;\r
-\r
-      } else if ((Temp & 0xe0) == 0xc0) {\r
-        //\r
-        // two-byte utf8 char\r
-        //\r
-        *ValidBytes         = 2;\r
-\r
-        Utf8Char->Utf8_2[1] = Temp;\r
-\r
-      } else if ((Temp & 0xf0) == 0xe0) {\r
-        //\r
-        // three-byte utf8 char\r
-        //\r
-        *ValidBytes         = 3;\r
-\r
-        Utf8Char->Utf8_3[2] = Temp;\r
-\r
-        Index++;\r
-\r
-      } else {\r
-        //\r
-        // reset *ValidBytes to zero, let valid utf8 char search restart\r
-        //\r
-        *ValidBytes = 0;\r
-      }\r
-\r
-      break;\r
-\r
-    case 2:\r
-      //\r
-      // two-byte utf8 char go on\r
-      //\r
-      if ((Temp & 0xc0) == 0x80) {\r
-\r
-        Utf8Char->Utf8_2[0] = Temp;\r
-\r
-        FetchFlag           = FALSE;\r
-\r
-      } else {\r
-\r
-        *ValidBytes = 0;\r
-      }\r
-      break;\r
-\r
-    case 3:\r
-      //\r
-      // three-byte utf8 char go on\r
-      //\r
-      if ((Temp & 0xc0) == 0x80) {\r
-        if (Index == 1) {\r
-          Utf8Char->Utf8_3[1] = Temp;\r
-          Index++;\r
-        } else {\r
-          Utf8Char->Utf8_3[0] = Temp;\r
-          FetchFlag = FALSE;\r
-        }\r
-      } else {\r
-        //\r
-        // reset *ValidBytes and Index to zero, let valid utf8 char search restart\r
-        //\r
-        *ValidBytes = 0;\r
-        Index       = 0;\r
-      }\r
-      break;\r
-\r
-    default:\r
-      break;\r
-    }\r
-\r
-    if (!FetchFlag) {\r
-      break;\r
-    }\r
-  }\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  Translate VT-UTF8 characters into one Unicode character.\r
-\r
-  UTF8 Encoding Table\r
-  Bits per Character | Unicode Character Range | Unicode Binary  Encoding |    UTF8 Binary Encoding\r
-        0-7             |     0x0000 - 0x007F     |     00000000 0xxxxxxx        |   0xxxxxxx\r
-        8-11          |     0x0080 - 0x07FF       |     00000xxx xxxxxxxx        |   110xxxxx 10xxxxxx\r
-       12-16          |     0x0800 - 0xFFFF       |     xxxxxxxx xxxxxxxx        |   1110xxxx 10xxxxxx 10xxxxxx\r
-\r
-\r
-  @param  Utf8Char         VT-UTF8 character set needs translating.\r
-  @param  ValidBytes       The count of valid VT-UTF8 characters.\r
-  @param  UnicodeChar      Returned unicode character.\r
-\r
-**/\r
-VOID\r
-Utf8ToUnicode (\r
-  IN  UTF8_CHAR       Utf8Char,\r
-  IN  UINT8           ValidBytes,\r
-  OUT CHAR16          *UnicodeChar\r
-  )\r
-{\r
-  UINT8 UnicodeByte0;\r
-  UINT8 UnicodeByte1;\r
-  UINT8 Byte0;\r
-  UINT8 Byte1;\r
-  UINT8 Byte2;\r
-\r
-  *UnicodeChar = 0;\r
-\r
-  //\r
-  // translate utf8 code to unicode, in terminal standard,\r
-  // up to 3 bytes utf8 code is supported.\r
-  //\r
-  switch (ValidBytes) {\r
-  case 1:\r
-    //\r
-    // one-byte utf8 code\r
-    //\r
-    *UnicodeChar = (UINT16) Utf8Char.Utf8_1;\r
-    break;\r
-\r
-  case 2:\r
-    //\r
-    // two-byte utf8 code\r
-    //\r
-    Byte0         = Utf8Char.Utf8_2[0];\r
-    Byte1         = Utf8Char.Utf8_2[1];\r
-\r
-    UnicodeByte0  = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f));\r
-    UnicodeByte1  = (UINT8) ((Byte1 >> 2) & 0x07);\r
-    *UnicodeChar  = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8));\r
-    break;\r
-\r
-  case 3:\r
-    //\r
-    // three-byte utf8 code\r
-    //\r
-    Byte0         = Utf8Char.Utf8_3[0];\r
-    Byte1         = Utf8Char.Utf8_3[1];\r
-    Byte2         = Utf8Char.Utf8_3[2];\r
-\r
-    UnicodeByte0  = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f));\r
-    UnicodeByte1  = (UINT8) ((Byte2 << 4) | ((Byte1 >> 2) & 0x0f));\r
-    *UnicodeChar  = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8));\r
-\r
-  default:\r
-    break;\r
-  }\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  Translate one Unicode character into VT-UTF8 characters.\r
-\r
-  UTF8 Encoding Table\r
-  Bits per Character | Unicode Character Range | Unicode Binary  Encoding |    UTF8 Binary Encoding\r
-        0-7             |     0x0000 - 0x007F     |     00000000 0xxxxxxx        |   0xxxxxxx\r
-        8-11          |     0x0080 - 0x07FF       |     00000xxx xxxxxxxx        |   110xxxxx 10xxxxxx\r
-       12-16          |     0x0800 - 0xFFFF       |     xxxxxxxx xxxxxxxx        |   1110xxxx 10xxxxxx 10xxxxxx\r
-\r
-\r
-  @param  Unicode          Unicode character need translating.\r
-  @param  Utf8Char         Return VT-UTF8 character set.\r
-  @param  ValidBytes       The count of valid VT-UTF8 characters. If\r
-                           ValidBytes is zero, no valid VT-UTF8 returned.\r
-\r
-**/\r
-VOID\r
-UnicodeToUtf8 (\r
-  IN  CHAR16      Unicode,\r
-  OUT UTF8_CHAR   *Utf8Char,\r
-  OUT UINT8       *ValidBytes\r
-  )\r
-{\r
-  UINT8 UnicodeByte0;\r
-  UINT8 UnicodeByte1;\r
-  //\r
-  // translate unicode to utf8 code\r
-  //\r
-  UnicodeByte0  = (UINT8) Unicode;\r
-  UnicodeByte1  = (UINT8) (Unicode >> 8);\r
-\r
-  if (Unicode < 0x0080) {\r
-\r
-    Utf8Char->Utf8_1  = (UINT8) (UnicodeByte0 & 0x7f);\r
-    *ValidBytes       = 1;\r
-\r
-  } else if (Unicode < 0x0800) {\r
-    //\r
-    // byte sequence: high -> low\r
-    //                Utf8_2[0], Utf8_2[1]\r
-    //\r
-    Utf8Char->Utf8_2[1] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80);\r
-    Utf8Char->Utf8_2[0] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x1f) + 0xc0);\r
-\r
-    *ValidBytes         = 2;\r
-\r
-  } else {\r
-    //\r
-    // byte sequence: high -> low\r
-    //                Utf8_3[0], Utf8_3[1], Utf8_3[2]\r
-    //\r
-    Utf8Char->Utf8_3[2] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80);\r
-    Utf8Char->Utf8_3[1] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x3f) + 0x80);\r
-    Utf8Char->Utf8_3[0] = (UINT8) (((UnicodeByte1 >> 4) & 0x0f) + 0xe0);\r
-\r
-    *ValidBytes         = 3;\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Check if input string is valid VT-UTF8 string.\r
-\r
-  @param  TerminalDevice          The terminal device.\r
-  @param  WString                 The input string.\r
-\r
-  @retval EFI_SUCCESS             If all input characters are valid.\r
-\r
-**/\r
-EFI_STATUS\r
-VTUTF8TestString (\r
-  IN  TERMINAL_DEV    *TerminalDevice,\r
-  IN  CHAR16          *WString\r
-  )\r
-{\r
-  //\r
-  // to utf8, all kind of characters are supported.\r
-  //\r
-  return EFI_SUCCESS;\r
-}\r
+/** @file
+  Implementation of translation upon VT-UTF8.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Terminal.h"
+
+/**
+  Translate all VT-UTF8 characters in the Raw FIFI into unicode characters,
+  and insert them into Unicode FIFO.
+
+  @param TerminalDevice          The terminal device.
+
+**/
+VOID
+VTUTF8RawDataToUnicode (
+  IN  TERMINAL_DEV    *TerminalDevice
+  )
+{
+  UTF8_CHAR Utf8Char;
+  UINT8     ValidBytes;
+  UINT16    UnicodeChar;
+
+  ValidBytes = 0;
+  //
+  // pop the raw data out from the raw fifo,
+  // and translate it into unicode, then push
+  // the unicode into unicode fifo, until the raw fifo is empty.
+  //
+  while (!IsRawFiFoEmpty (TerminalDevice) && !IsUnicodeFiFoFull(TerminalDevice) ) {
+
+    GetOneValidUtf8Char (TerminalDevice, &Utf8Char, &ValidBytes);
+
+    if (ValidBytes < 1 || ValidBytes > 3) {
+      continue;
+    }
+
+    Utf8ToUnicode (Utf8Char, ValidBytes, (CHAR16 *) &UnicodeChar);
+
+    UnicodeFiFoInsertOneKey (TerminalDevice, UnicodeChar);
+  }
+}
+
+/**
+  Get one valid VT-UTF8 characters set from Raw Data FIFO.
+
+  @param  Utf8Device          The terminal device.
+  @param  Utf8Char            Returned valid VT-UTF8 characters set.
+  @param  ValidBytes          The count of returned VT-VTF8 characters.
+                              If ValidBytes is zero, no valid VT-UTF8 returned.
+
+**/
+VOID
+GetOneValidUtf8Char (
+  IN  TERMINAL_DEV      *Utf8Device,
+  OUT UTF8_CHAR         *Utf8Char,
+  OUT UINT8             *ValidBytes
+  )
+{
+  UINT8   Temp;
+  UINT8   Index;
+  BOOLEAN FetchFlag;
+
+  Temp      = 0;
+  Index     = 0;
+  FetchFlag = TRUE;
+
+  //
+  // if no valid Utf8 char is found in the RawFiFo,
+  // then *ValidBytes will be zero.
+  //
+  *ValidBytes = 0;
+
+  while (!IsRawFiFoEmpty (Utf8Device)) {
+
+    RawFiFoRemoveOneKey (Utf8Device, &Temp);
+
+    switch (*ValidBytes) {
+
+    case 0:
+      if ((Temp & 0x80) == 0) {
+        //
+        // one-byte utf8 char
+        //
+        *ValidBytes       = 1;
+
+        Utf8Char->Utf8_1  = Temp;
+
+        FetchFlag         = FALSE;
+
+      } else if ((Temp & 0xe0) == 0xc0) {
+        //
+        // two-byte utf8 char
+        //
+        *ValidBytes         = 2;
+
+        Utf8Char->Utf8_2[1] = Temp;
+
+      } else if ((Temp & 0xf0) == 0xe0) {
+        //
+        // three-byte utf8 char
+        //
+        *ValidBytes         = 3;
+
+        Utf8Char->Utf8_3[2] = Temp;
+
+        Index++;
+
+      } else {
+        //
+        // reset *ValidBytes to zero, let valid utf8 char search restart
+        //
+        *ValidBytes = 0;
+      }
+
+      break;
+
+    case 2:
+      //
+      // two-byte utf8 char go on
+      //
+      if ((Temp & 0xc0) == 0x80) {
+
+        Utf8Char->Utf8_2[0] = Temp;
+
+        FetchFlag           = FALSE;
+
+      } else {
+
+        *ValidBytes = 0;
+      }
+      break;
+
+    case 3:
+      //
+      // three-byte utf8 char go on
+      //
+      if ((Temp & 0xc0) == 0x80) {
+        if (Index == 1) {
+          Utf8Char->Utf8_3[1] = Temp;
+          Index++;
+        } else {
+          Utf8Char->Utf8_3[0] = Temp;
+          FetchFlag = FALSE;
+        }
+      } else {
+        //
+        // reset *ValidBytes and Index to zero, let valid utf8 char search restart
+        //
+        *ValidBytes = 0;
+        Index       = 0;
+      }
+      break;
+
+    default:
+      break;
+    }
+
+    if (!FetchFlag) {
+      break;
+    }
+  }
+
+  return ;
+}
+
+/**
+  Translate VT-UTF8 characters into one Unicode character.
+
+  UTF8 Encoding Table
+  Bits per Character | Unicode Character Range | Unicode Binary  Encoding |    UTF8 Binary Encoding
+        0-7             |     0x0000 - 0x007F     |     00000000 0xxxxxxx        |   0xxxxxxx
+        8-11          |     0x0080 - 0x07FF       |     00000xxx xxxxxxxx        |   110xxxxx 10xxxxxx
+       12-16          |     0x0800 - 0xFFFF       |     xxxxxxxx xxxxxxxx        |   1110xxxx 10xxxxxx 10xxxxxx
+
+
+  @param  Utf8Char         VT-UTF8 character set needs translating.
+  @param  ValidBytes       The count of valid VT-UTF8 characters.
+  @param  UnicodeChar      Returned unicode character.
+
+**/
+VOID
+Utf8ToUnicode (
+  IN  UTF8_CHAR       Utf8Char,
+  IN  UINT8           ValidBytes,
+  OUT CHAR16          *UnicodeChar
+  )
+{
+  UINT8 UnicodeByte0;
+  UINT8 UnicodeByte1;
+  UINT8 Byte0;
+  UINT8 Byte1;
+  UINT8 Byte2;
+
+  *UnicodeChar = 0;
+
+  //
+  // translate utf8 code to unicode, in terminal standard,
+  // up to 3 bytes utf8 code is supported.
+  //
+  switch (ValidBytes) {
+  case 1:
+    //
+    // one-byte utf8 code
+    //
+    *UnicodeChar = (UINT16) Utf8Char.Utf8_1;
+    break;
+
+  case 2:
+    //
+    // two-byte utf8 code
+    //
+    Byte0         = Utf8Char.Utf8_2[0];
+    Byte1         = Utf8Char.Utf8_2[1];
+
+    UnicodeByte0  = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f));
+    UnicodeByte1  = (UINT8) ((Byte1 >> 2) & 0x07);
+    *UnicodeChar  = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8));
+    break;
+
+  case 3:
+    //
+    // three-byte utf8 code
+    //
+    Byte0         = Utf8Char.Utf8_3[0];
+    Byte1         = Utf8Char.Utf8_3[1];
+    Byte2         = Utf8Char.Utf8_3[2];
+
+    UnicodeByte0  = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f));
+    UnicodeByte1  = (UINT8) ((Byte2 << 4) | ((Byte1 >> 2) & 0x0f));
+    *UnicodeChar  = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8));
+
+  default:
+    break;
+  }
+
+  return ;
+}
+
+/**
+  Translate one Unicode character into VT-UTF8 characters.
+
+  UTF8 Encoding Table
+  Bits per Character | Unicode Character Range | Unicode Binary  Encoding |    UTF8 Binary Encoding
+        0-7             |     0x0000 - 0x007F     |     00000000 0xxxxxxx        |   0xxxxxxx
+        8-11          |     0x0080 - 0x07FF       |     00000xxx xxxxxxxx        |   110xxxxx 10xxxxxx
+       12-16          |     0x0800 - 0xFFFF       |     xxxxxxxx xxxxxxxx        |   1110xxxx 10xxxxxx 10xxxxxx
+
+
+  @param  Unicode          Unicode character need translating.
+  @param  Utf8Char         Return VT-UTF8 character set.
+  @param  ValidBytes       The count of valid VT-UTF8 characters. If
+                           ValidBytes is zero, no valid VT-UTF8 returned.
+
+**/
+VOID
+UnicodeToUtf8 (
+  IN  CHAR16      Unicode,
+  OUT UTF8_CHAR   *Utf8Char,
+  OUT UINT8       *ValidBytes
+  )
+{
+  UINT8 UnicodeByte0;
+  UINT8 UnicodeByte1;
+  //
+  // translate unicode to utf8 code
+  //
+  UnicodeByte0  = (UINT8) Unicode;
+  UnicodeByte1  = (UINT8) (Unicode >> 8);
+
+  if (Unicode < 0x0080) {
+
+    Utf8Char->Utf8_1  = (UINT8) (UnicodeByte0 & 0x7f);
+    *ValidBytes       = 1;
+
+  } else if (Unicode < 0x0800) {
+    //
+    // byte sequence: high -> low
+    //                Utf8_2[0], Utf8_2[1]
+    //
+    Utf8Char->Utf8_2[1] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80);
+    Utf8Char->Utf8_2[0] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x1f) + 0xc0);
+
+    *ValidBytes         = 2;
+
+  } else {
+    //
+    // byte sequence: high -> low
+    //                Utf8_3[0], Utf8_3[1], Utf8_3[2]
+    //
+    Utf8Char->Utf8_3[2] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80);
+    Utf8Char->Utf8_3[1] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x3f) + 0x80);
+    Utf8Char->Utf8_3[0] = (UINT8) (((UnicodeByte1 >> 4) & 0x0f) + 0xe0);
+
+    *ValidBytes         = 3;
+  }
+}
+
+
+/**
+  Check if input string is valid VT-UTF8 string.
+
+  @param  TerminalDevice          The terminal device.
+  @param  WString                 The input string.
+
+  @retval EFI_SUCCESS             If all input characters are valid.
+
+**/
+EFI_STATUS
+VTUTF8TestString (
+  IN  TERMINAL_DEV    *TerminalDevice,
+  IN  CHAR16          *WString
+  )
+{
+  //
+  // to utf8, all kind of characters are supported.
+  //
+  return EFI_SUCCESS;
+}