]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / Terminal.c
index 511094844b0503ea70e380610d89f43519c90463..e2d779c783784e7a06745e55c9f04548c8c5a652 100644 (file)
@@ -2,24 +2,17 @@
   Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and\r
   Simple Text Output Protocol upon Serial IO Protocol.\r
 \r
-Copyright (c) 2006 - 2014, 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
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-\r
 #include "Terminal.h"\r
 \r
 //\r
 // Globals\r
 //\r
-EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {\r
+EFI_DRIVER_BINDING_PROTOCOL  gTerminalDriverBinding = {\r
   TerminalDriverBindingSupported,\r
   TerminalDriverBindingStart,\r
   TerminalDriverBindingStop,\r
@@ -28,14 +21,29 @@ EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {
   NULL\r
 };\r
 \r
-\r
-EFI_GUID  *gTerminalType[] = {\r
+EFI_GUID  *mTerminalType[] = {\r
   &gEfiPcAnsiGuid,\r
   &gEfiVT100Guid,\r
   &gEfiVT100PlusGuid,\r
-  &gEfiVTUTF8Guid\r
+  &gEfiVTUTF8Guid,\r
+  &gEfiTtyTermGuid,\r
+  &gEdkiiLinuxTermGuid,\r
+  &gEdkiiXtermR6Guid,\r
+  &gEdkiiVT400Guid,\r
+  &gEdkiiSCOTermGuid\r
 };\r
 \r
+CHAR16  *mSerialConsoleNames[] = {\r
+  L"PC-ANSI Serial Console",\r
+  L"VT-100 Serial Console",\r
+  L"VT-100+ Serial Console",\r
+  L"VT-UTF8 Serial Console",\r
+  L"Tty Terminal Serial Console",\r
+  L"Linux Terminal Serial Console",\r
+  L"Xterm R6 Serial Console",\r
+  L"VT-400 Serial Console",\r
+  L"SCO Terminal Serial Console"\r
+};\r
 \r
 TERMINAL_DEV  mTerminalDevTemplate = {\r
   TERMINAL_DEV_SIGNATURE,\r
@@ -60,26 +68,33 @@ TERMINAL_DEV  mTerminalDevTemplate = {
     TerminalConOutEnableCursor,\r
     NULL\r
   },\r
-  {   // SimpleTextOutputMode\r
-    1,                                           // MaxMode\r
-    0,                                           // Mode\r
-    EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK),    // Attribute\r
-    0,                                           // CursorColumn\r
-    0,                                           // CursorRow\r
-    TRUE                                         // CursorVisible\r
+  {                                           // SimpleTextOutputMode\r
+    1,                                        // MaxMode\r
+    0,                                        // Mode\r
+    EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
+    0,                                        // CursorColumn\r
+    0,                                        // CursorRow\r
+    TRUE                                      // CursorVisible\r
   },\r
   NULL, // TerminalConsoleModeData\r
-  0,  // SerialInTimeOut\r
+  0,    // SerialInTimeOut\r
 \r
   NULL, // RawFifo\r
   NULL, // UnicodeFiFo\r
   NULL, // EfiKeyFiFo\r
+  NULL, // EfiKeyFiFoForNotify\r
 \r
   NULL, // ControllerNameTable\r
   NULL, // TimerEvent\r
   NULL, // TwoSecondTimeOut\r
   INPUT_STATE_DEFAULT,\r
   RESET_STATE_DEFAULT,\r
+  {\r
+    0,\r
+    0,\r
+    0\r
+  },\r
+  0,\r
   FALSE,\r
   {   // SimpleTextInputEx\r
     TerminalConInResetEx,\r
@@ -92,16 +107,42 @@ TERMINAL_DEV  mTerminalDevTemplate = {
   {   // NotifyList\r
     NULL,\r
     NULL,\r
-  }\r
+  },\r
+  NULL // KeyNotifyProcessEvent\r
 };\r
 \r
-TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
-  {100, 31},\r
+TERMINAL_CONSOLE_MODE_DATA  mTerminalConsoleModeData[] = {\r
+  { 80,  25 },\r
+  { 80,  50 },\r
+  { 100, 31 },\r
   //\r
   // New modes can be added here.\r
   //\r
 };\r
 \r
+/**\r
+  Convert the GUID representation of terminal type to enum type.\r
+\r
+  @param Guid  The GUID representation of terminal type.\r
+\r
+  @return  The terminal type in enum type.\r
+**/\r
+TERMINAL_TYPE\r
+TerminalTypeFromGuid (\r
+  IN EFI_GUID  *Guid\r
+  )\r
+{\r
+  TERMINAL_TYPE  Type;\r
+\r
+  for (Type = 0; Type < ARRAY_SIZE (mTerminalType); Type++) {\r
+    if (CompareGuid (Guid, mTerminalType[Type])) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Type;\r
+}\r
+\r
 /**\r
   Test to see if this driver supports Controller.\r
 \r
@@ -118,9 +159,9 @@ TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {
 EFI_STATUS\r
 EFIAPI\r
 TerminalDriverBindingSupported (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
-  IN EFI_HANDLE                     Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -142,27 +183,25 @@ TerminalDriverBindingSupported (
       // If RemainingDevicePath isn't the End of Device Path Node,\r
       // check its validation\r
       //\r
-      Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
-\r
-      if (Node->Header.Type != MESSAGING_DEVICE_PATH ||\r
-          Node->Header.SubType != MSG_VENDOR_DP ||\r
-          DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {\r
+      Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
 \r
+      if ((Node->Header.Type != MESSAGING_DEVICE_PATH) ||\r
+          (Node->Header.SubType != MSG_VENDOR_DP) ||\r
+          (DevicePathNodeLength (&Node->Header) != sizeof (VENDOR_DEVICE_PATH)))\r
+      {\r
         return EFI_UNSUPPORTED;\r
-\r
       }\r
+\r
       //\r
-      // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types\r
+      // only supports PC ANSI, VT100, VT100+, VT-UTF8, TtyTerm\r
+      // Linux, XtermR6, VT400 and SCO terminal types\r
       //\r
-      if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
-          !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
-          !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
-          !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
-\r
+      if (TerminalTypeFromGuid (&Node->Guid) == ARRAY_SIZE (mTerminalType)) {\r
         return EFI_UNSUPPORTED;\r
       }\r
     }\r
   }\r
+\r
   //\r
   // Open the IO Abstraction(s) needed to perform the supported test\r
   // The Controller must support the Serial I/O Protocol.\r
@@ -172,7 +211,7 @@ TerminalDriverBindingSupported (
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiSerialIoProtocolGuid,\r
-                  (VOID **) &SerialIo,\r
+                  (VOID **)&SerialIo,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -189,11 +228,11 @@ TerminalDriverBindingSupported (
   // Close the I/O Abstraction(s) used to perform the supported test\r
   //\r
   gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiSerialIoProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
+         Controller,\r
+         &gEfiSerialIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
 \r
   //\r
   // Open the EFI Device Path protocol needed to perform the supported test\r
@@ -201,7 +240,7 @@ TerminalDriverBindingSupported (
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
+                  (VOID **)&ParentDevicePath,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -218,291 +257,196 @@ TerminalDriverBindingSupported (
   // Close protocol, don't use device path protocol in the Support() function\r
   //\r
   gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiDevicePathProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
+         Controller,\r
+         &gEfiDevicePathProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
 \r
   return Status;\r
 }\r
 \r
 /**\r
-  Build the terminal device path for the child device according to the\r
-  terminal type.\r
+  Free notify functions list.\r
 \r
-  @param  ParentDevicePath         Parent device path.\r
-  @param  RemainingDevicePath      A specific child device.\r
+  @param  ListHead               The list head\r
 \r
-  @return The child device path built.\r
+  @retval EFI_SUCCESS            Free the notify list successfully.\r
+  @retval EFI_INVALID_PARAMETER  ListHead is NULL.\r
 \r
 **/\r
-EFI_DEVICE_PATH_PROTOCOL*\r
-EFIAPI\r
-BuildTerminalDevpath  (\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *ParentDevicePath,\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+  IN OUT LIST_ENTRY  *ListHead\r
   )\r
 {\r
-  EFI_DEVICE_PATH_PROTOCOL          *TerminalDevicePath;\r
-  UINT8                             TerminalType;\r
-  VENDOR_DEVICE_PATH                *Node;\r
-  EFI_STATUS                        Status;\r
-\r
-  TerminalDevicePath = NULL;\r
-  TerminalType = PCANSITYPE;\r
-\r
-  //\r
-  // Use the RemainingDevicePath to determine the terminal type\r
-  //\r
-  Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
-  if (Node == NULL) {\r
-    TerminalType = PCANSITYPE;\r
-\r
-  } else if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
-\r
-    TerminalType = PCANSITYPE;\r
-\r
-  } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
-\r
-    TerminalType = VT100TYPE;\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY  *NotifyNode;\r
 \r
-  } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
-\r
-    TerminalType = VT100PLUSTYPE;\r
-\r
-  } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
-\r
-    TerminalType = VTUTF8TYPE;\r
-\r
-  } else {\r
-    return NULL;\r
+  if (ListHead == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  //\r
-  // Build the device path for the child device\r
-  //\r
-  Status = SetTerminalDevicePath (\r
-            TerminalType,\r
-            ParentDevicePath,\r
-            &TerminalDevicePath\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
+  while (!IsListEmpty (ListHead)) {\r
+    NotifyNode = CR (\r
+                   ListHead->ForwardLink,\r
+                   TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
+                   NotifyEntry,\r
+                   TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                   );\r
+    RemoveEntryList (ListHead->ForwardLink);\r
+    FreePool (NotifyNode);\r
   }\r
-  return TerminalDevicePath;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Compare a device path data structure to that of all the nodes of a\r
-  second device path instance.\r
+  Initialize all the text modes which the terminal console supports.\r
 \r
-  @param  Multi          A pointer to a multi-instance device path data structure.\r
-  @param  Single         A pointer to a single-instance device path data structure.\r
+  It returns information for available text modes that the terminal can support.\r
 \r
-  @retval TRUE           If the Single is contained within Multi.\r
-  @retval FALSE          The Single is not match within Multi.\r
+  @param[out] TextModeCount      The total number of text modes that terminal console supports.\r
+\r
+  @return   The buffer to the text modes column and row information.\r
+            Caller is responsible to free it when it's non-NULL.\r
 \r
 **/\r
-BOOLEAN\r
-MatchDevicePaths (\r
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Single\r
+TERMINAL_CONSOLE_MODE_DATA *\r
+InitializeTerminalConsoleTextMode (\r
+  OUT INT32  *TextModeCount\r
   )\r
 {\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
-  UINTN                     Size;\r
+  TERMINAL_CONSOLE_MODE_DATA  *TextModeData;\r
 \r
-  DevicePath      = Multi;\r
-  DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
-  //\r
-  // Search for the match of 'Single' in 'Multi'\r
-  //\r
-  while (DevicePathInst != NULL) {\r
-    //\r
-    // If the single device path is found in multiple device paths,\r
-    // return success\r
-    //\r
-    if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
-      FreePool (DevicePathInst);\r
-      return TRUE;\r
-    }\r
+  ASSERT (TextModeCount != NULL);\r
 \r
-    FreePool (DevicePathInst);\r
-    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+  TextModeData = AllocateCopyPool (sizeof (mTerminalConsoleModeData), mTerminalConsoleModeData);\r
+  if (TextModeData == NULL) {\r
+    return NULL;\r
   }\r
 \r
-  return FALSE;\r
-}\r
+  *TextModeCount = ARRAY_SIZE (mTerminalConsoleModeData);\r
 \r
-/**\r
-  Check whether the terminal device path is in the global variable.\r
+  DEBUG_CODE_BEGIN ();\r
+  INT32  Index;\r
 \r
-  @param  VariableName          Pointer to one global variable.\r
-  @param  TerminalDevicePath    Pointer to the terminal device's device path.\r
+  for (Index = 0; Index < *TextModeCount; Index++) {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "Terminal - Mode %d, Column = %d, Row = %d\n",\r
+      Index,\r
+      TextModeData[Index].Columns,\r
+      TextModeData[Index].Rows\r
+      ));\r
+  }\r
 \r
-  @retval TRUE                  The devcie is in the global variable.\r
-  @retval FALSE                 The devcie is not in the global variable.\r
+  DEBUG_CODE_END ();\r
+  return TextModeData;\r
+}\r
+\r
+/**\r
+  Stop the terminal state machine.\r
 \r
+  @param TerminalDevice    The terminal device.\r
 **/\r
-BOOLEAN\r
-IsTerminalInConsoleVariable (\r
-  IN CHAR16                    *VariableName,\r
-  IN EFI_DEVICE_PATH_PROTOCOL  *TerminalDevicePath\r
+VOID\r
+StopTerminalStateMachine (\r
+  TERMINAL_DEV  *TerminalDevice\r
   )\r
 {\r
-  EFI_DEVICE_PATH_PROTOCOL  *Variable;\r
-  BOOLEAN                   ReturnFlag;\r
-\r
-  //\r
-  // Get global variable and its size according to the name given.\r
-  //\r
-  GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
-  if (Variable == NULL) {\r
-    return FALSE;\r
-  }\r
+  EFI_TPL  OriginalTpl;\r
 \r
-  //\r
-  // Check whether the terminal device path is one of the variable instances.\r
-  //\r
-  ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
+  OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
 \r
-  FreePool (Variable);\r
+  gBS->CloseEvent (TerminalDevice->TimerEvent);\r
+  gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
 \r
-  return ReturnFlag;\r
+  gBS->RestoreTPL (OriginalTpl);\r
 }\r
 \r
 /**\r
-  Free notify functions list.\r
-\r
-  @param  ListHead               The list head\r
-\r
-  @retval EFI_SUCCESS            Free the notify list successfully.\r
-  @retval EFI_INVALID_PARAMETER  ListHead is NULL.\r
+  Start the terminal state machine.\r
 \r
+  @param TerminalDevice    The terminal device.\r
 **/\r
-EFI_STATUS\r
-TerminalFreeNotifyList (\r
-  IN OUT LIST_ENTRY           *ListHead\r
+VOID\r
+StartTerminalStateMachine (\r
+  TERMINAL_DEV  *TerminalDevice\r
   )\r
 {\r
-  TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  TerminalConInTimerHandler,\r
+                  TerminalDevice,\r
+                  &TerminalDevice->TimerEvent\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-  if (ListHead == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  while (!IsListEmpty (ListHead)) {\r
-    NotifyNode = CR (\r
-                   ListHead->ForwardLink,\r
-                   TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
-                   NotifyEntry,\r
-                   TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
-                   );\r
-    RemoveEntryList (ListHead->ForwardLink);\r
-    FreePool (NotifyNode);\r
-  }\r
+  Status = gBS->SetTimer (\r
+                  TerminalDevice->TimerEvent,\r
+                  TimerPeriodic,\r
+                  KEYBOARD_TIMER_INTERVAL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-  return EFI_SUCCESS;\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER,\r
+                  TPL_CALLBACK,\r
+                  NULL,\r
+                  NULL,\r
+                  &TerminalDevice->TwoSecondTimeOut\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r
-  Initialize all the text modes which the terminal console supports.\r
-\r
-  It returns information for available text modes that the terminal can support.\r
+  Initialize the controller name table.\r
 \r
-  @param[out] TextModeCount      The total number of text modes that terminal console supports.\r
-  @param[out] TextModeData       The buffer to the text modes column and row information.\r
-                                 Caller is responsible to free it when it's non-NULL.\r
-\r
-  @retval EFI_SUCCESS            The supporting mode information is returned.\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
+  @param TerminalType        The terminal type.\r
+  @param ControllerNameTable The controller name table.\r
 \r
+  @retval EFI_SUCCESS  The controller name table is initialized successfully.\r
+  @retval others       Return status of AddUnicodeString2 ().\r
 **/\r
 EFI_STATUS\r
-InitializeTerminalConsoleTextMode (\r
-  OUT UINTN                         *TextModeCount,\r
-  OUT TERMINAL_CONSOLE_MODE_DATA    **TextModeData\r
+InitializeControllerNameTable (\r
+  TERMINAL_TYPE             TerminalType,\r
+  EFI_UNICODE_STRING_TABLE  **ControllerNameTable\r
   )\r
 {\r
-  UINTN                       Index;\r
-  UINTN                       Count;\r
-  TERMINAL_CONSOLE_MODE_DATA  *ModeBuffer;\r
-  TERMINAL_CONSOLE_MODE_DATA  *NewModeBuffer;\r
-  UINTN                       ValidCount;\r
-  UINTN                       ValidIndex;\r
-  \r
-  if ((TextModeCount == NULL) || (TextModeData == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
+  EFI_STATUS                Status;\r
+  EFI_UNICODE_STRING_TABLE  *Table;\r
+\r
+  ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
+  Table  = NULL;\r
+  Status = AddUnicodeString2 (\r
+             "eng",\r
+             gTerminalComponentName.SupportedLanguages,\r
+             &Table,\r
+             mSerialConsoleNames[TerminalType],\r
+             TRUE\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = AddUnicodeString2 (\r
+               "en",\r
+               gTerminalComponentName2.SupportedLanguages,\r
+               &Table,\r
+               mSerialConsoleNames[TerminalType],\r
+               FALSE\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      FreeUnicodeStringTable (Table);\r
+    }\r
   }\r
-  \r
-  Count = sizeof (mTerminalConsoleModeData) / sizeof (TERMINAL_CONSOLE_MODE_DATA);\r
-  \r
-  //\r
-  // Get defined mode buffer pointer.\r
-  //\r
-  ModeBuffer = mTerminalConsoleModeData;\r
-    \r
-  //\r
-  // Here we make sure that the final mode exposed does not include the duplicated modes,\r
-  // and does not include the invalid modes which exceed the max column and row.\r
-  // Reserve 2 modes for 80x25, 80x50 of terminal console.\r
-  //\r
-  NewModeBuffer = AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA) * (Count + 2));\r
-  ASSERT (NewModeBuffer != NULL);\r
-\r
-  //\r
-  // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
-  //\r
-  ValidCount = 0;  \r
-\r
-  NewModeBuffer[ValidCount].Columns = 80;\r
-  NewModeBuffer[ValidCount].Rows    = 25;\r
-  ValidCount++;\r
 \r
-  NewModeBuffer[ValidCount].Columns = 80;\r
-  NewModeBuffer[ValidCount].Rows    = 50;\r
-  ValidCount++;\r
-  \r
-  //\r
-  // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.\r
-  //\r
-  for (Index = 0; Index < Count; Index++) {\r
-    if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0)) {\r
-      //\r
-      // Skip the pre-defined mode which is invalid.\r
-      //\r
-      continue;\r
-    }\r
-    for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {\r
-      if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&\r
-          (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {\r
-        //\r
-        // Skip the duplicated mode.\r
-        //\r
-        break;\r
-      }\r
-    }\r
-    if (ValidIndex == ValidCount) {\r
-      NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;\r
-      NewModeBuffer[ValidCount].Rows    = ModeBuffer[Index].Rows;\r
-      ValidCount++;\r
-    }\r
+  if (!EFI_ERROR (Status)) {\r
+    *ControllerNameTable = Table;\r
   }\r
\r
-  DEBUG_CODE (\r
-    for (Index = 0; Index < ValidCount; Index++) {\r
-      DEBUG ((EFI_D_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n", \r
-                           Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows));  \r
-    }\r
-  );\r
-  \r
-  //\r
-  // Return valid mode count and mode information buffer.\r
-  //\r
-  *TextModeCount = ValidCount;\r
-  *TextModeData  = NewModeBuffer;\r
-  return EFI_SUCCESS;\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -524,54 +468,40 @@ InitializeTerminalConsoleTextMode (
 EFI_STATUS\r
 EFIAPI\r
 TerminalDriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
-  IN EFI_HANDLE                     Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
-  EFI_STATUS                          Status;\r
-  EFI_SERIAL_IO_PROTOCOL              *SerialIo;\r
-  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;\r
-  VENDOR_DEVICE_PATH                  *Node;\r
-  VENDOR_DEVICE_PATH                  *DefaultNode;\r
-  EFI_SERIAL_IO_MODE                  *Mode;\r
-  UINTN                               SerialInTimeOut;\r
-  TERMINAL_DEV                        *TerminalDevice;\r
-  UINT8                               TerminalType;\r
-  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
-  UINTN                               EntryCount;\r
-  UINTN                               Index;\r
-  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
-  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL     *SimpleTextOutput;\r
-  EFI_SIMPLE_TEXT_INPUT_PROTOCOL      *SimpleTextInput;\r
-  BOOLEAN                             ConInSelected;\r
-  BOOLEAN                             ConOutSelected;\r
-  BOOLEAN                             NullRemaining;\r
-  BOOLEAN                             SimTxtInInstalled;\r
-  BOOLEAN                             SimTxtOutInstalled;\r
-  BOOLEAN                             FirstEnter;\r
-  UINTN                               ModeCount;\r
-\r
-  TerminalDevice     = NULL;\r
-  DefaultNode        = NULL;\r
-  ConInSelected       = FALSE;\r
-  ConOutSelected      = FALSE;\r
-  NullRemaining      = TRUE;\r
-  SimTxtInInstalled  = FALSE;\r
-  SimTxtOutInstalled = FALSE;\r
-  FirstEnter         = FALSE;\r
+  EFI_STATUS                           Status;\r
+  EFI_SERIAL_IO_PROTOCOL               *SerialIo;\r
+  EFI_DEVICE_PATH_PROTOCOL             *ParentDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL             *Vendor;\r
+  EFI_HANDLE                           SerialIoHandle;\r
+  EFI_SERIAL_IO_MODE                   *Mode;\r
+  UINTN                                SerialInTimeOut;\r
+  TERMINAL_DEV                         *TerminalDevice;\r
+  UINT8                                TerminalType;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;\r
+  UINTN                                EntryCount;\r
+  UINTN                                Index;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL      *SimpleTextOutput;\r
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL       *SimpleTextInput;\r
+  EFI_UNICODE_STRING_TABLE             *ControllerNameTable;\r
+\r
   //\r
   // Get the Device Path Protocol to build the device path of the child device\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
+                  (VOID **)&ParentDevicePath,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+  ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));\r
+  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
     return Status;\r
   }\r
 \r
@@ -581,100 +511,44 @@ TerminalDriverBindingStart (
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiSerialIoProtocolGuid,\r
-                  (VOID **) &SerialIo,\r
+                  (VOID **)&SerialIo,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+  ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));\r
+  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
     return Status;\r
   }\r
 \r
-  if (Status != EFI_ALREADY_STARTED) {\r
+  if (!IsHotPlugDevice (ParentDevicePath)) {\r
     //\r
-    // the serial I/O protocol never be opened before, it is the first\r
-    // time to start the serial Io controller\r
+    // if the serial device is a hot plug device, do not update the\r
+    // ConInDev, ConOutDev, and StdErrDev variables.\r
     //\r
-    FirstEnter = TRUE;\r
+    TerminalUpdateConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);\r
+    TerminalUpdateConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+    TerminalUpdateConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
   }\r
 \r
   //\r
-  // Serial I/O is not already open by this driver, then tag the handle\r
-  // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
-  // StdErrDev variables with the list of possible terminal types on this\r
-  // serial port.\r
+  // Do not create any child for END remaining device path.\r
   //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiCallerIdGuid,\r
-                  NULL,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                    &Controller,\r
-                    &gEfiCallerIdGuid,\r
-                    DuplicateDevicePath (ParentDevicePath),\r
-                    NULL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
+  if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
-    if (!IsHotPlugDevice (ParentDevicePath)) {\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    if (RemainingDevicePath == NULL) {\r
       //\r
-      // if the serial device is a hot plug device, do not update the\r
-      // ConInDev, ConOutDev, and StdErrDev variables.\r
+      // If RemainingDevicePath is NULL or is the End of Device Path Node\r
       //\r
-      TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
-      TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
-      TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
+      return EFI_SUCCESS;\r
     }\r
-  }\r
 \r
-  //\r
-  // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols\r
-  //\r
-  // Simple In/Out Protocol will not be installed onto the handle if the\r
-  // device path to the handle is not present in the ConIn/ConOut\r
-  // environment variable. But If RemainingDevicePath is NULL, then always\r
-  // produce both Simple In and Simple Text Output Protocols. This is required\r
-  // for the connect all sequences to make sure all possible consoles are\r
-  // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
-  //\r
-  if (RemainingDevicePath == NULL) {\r
-    NullRemaining = TRUE;\r
-  }\r
-\r
-  DevicePath = BuildTerminalDevpath (ParentDevicePath, RemainingDevicePath);\r
-  if (DevicePath != NULL) {\r
-    ConInSelected  = IsTerminalInConsoleVariable (L"ConIn", DevicePath);\r
-    ConOutSelected = IsTerminalInConsoleVariable (L"ConOut", DevicePath);\r
-    FreePool (DevicePath);\r
-  } else {\r
-    goto Error;\r
-  }\r
-  //\r
-  // Not create the child terminal handle if both Simple In/In Ex and\r
-  // Simple text Out protocols are not required to be published\r
-  //\r
-  if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
-    goto Error;\r
-  }\r
-\r
-  //\r
-  // create the child terminal handle during first entry\r
-  //\r
-  if (FirstEnter) {\r
-    //\r
-    // First enther the start funciton\r
     //\r
-    FirstEnter = FALSE;\r
-    //\r
-    // Make sure a child handle does not already exist.  This driver can only\r
-    // produce one child per serial port.\r
+    // This driver can only produce one child per serial port.\r
+    // Change its terminal type as remaining device path requests.\r
     //\r
     Status = gBS->OpenProtocolInformation (\r
                     Controller,\r
@@ -683,551 +557,330 @@ TerminalDriverBindingStart (
                     &EntryCount\r
                     );\r
     if (!EFI_ERROR (Status)) {\r
-      Status = EFI_SUCCESS;\r
+      Status = EFI_NOT_FOUND;\r
       for (Index = 0; Index < EntryCount; Index++) {\r
         if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
-          Status = EFI_ALREADY_STARTED;\r
+          Status = gBS->OpenProtocol (\r
+                          OpenInfoBuffer[Index].ControllerHandle,\r
+                          &gEfiSimpleTextInProtocolGuid,\r
+                          (VOID **)&SimpleTextInput,\r
+                          This->DriverBindingHandle,\r
+                          Controller,\r
+                          EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                          );\r
+          if (!EFI_ERROR (Status)) {\r
+            TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
+            TerminalType   = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *)RemainingDevicePath)->Guid);\r
+            ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
+            if (TerminalDevice->TerminalType != TerminalType) {\r
+              Status = InitializeControllerNameTable (TerminalType, &ControllerNameTable);\r
+              if (!EFI_ERROR (Status)) {\r
+                StopTerminalStateMachine (TerminalDevice);\r
+                //\r
+                // Update the device path\r
+                //\r
+                Vendor = TerminalDevice->DevicePath;\r
+                Status = gBS->LocateDevicePath (&gEfiSerialIoProtocolGuid, &Vendor, &SerialIoHandle);\r
+                ASSERT_EFI_ERROR (Status);\r
+                CopyGuid (&((VENDOR_DEVICE_PATH *)Vendor)->Guid, mTerminalType[TerminalType]);\r
+                Status = gBS->ReinstallProtocolInterface (\r
+                                TerminalDevice->Handle,\r
+                                &gEfiDevicePathProtocolGuid,\r
+                                TerminalDevice->DevicePath,\r
+                                TerminalDevice->DevicePath\r
+                                );\r
+                if (!EFI_ERROR (Status)) {\r
+                  TerminalDevice->TerminalType = TerminalType;\r
+                  StartTerminalStateMachine (TerminalDevice);\r
+                  FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
+                  TerminalDevice->ControllerNameTable = ControllerNameTable;\r
+                } else {\r
+                  //\r
+                  // Restore the device path on failure\r
+                  //\r
+                  CopyGuid (&((VENDOR_DEVICE_PATH *)Vendor)->Guid, mTerminalType[TerminalDevice->TerminalType]);\r
+                  FreeUnicodeStringTable (ControllerNameTable);\r
+                }\r
+              }\r
+            }\r
+          }\r
+\r
+          break;\r
         }\r
       }\r
 \r
       FreePool (OpenInfoBuffer);\r
-      if (EFI_ERROR (Status)) {\r
-          goto Error;\r
-      }\r
     }\r
 \r
-    //\r
-    // If RemainingDevicePath is NULL, then create default device path node\r
-    //\r
-    if (RemainingDevicePath == NULL) {\r
-      DefaultNode = AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH));\r
-      if (DefaultNode == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto Error;\r
-      }\r
-\r
-      TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
-      //\r
-      // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)\r
-      //\r
-      ASSERT (TerminalType <= VTUTF8TYPE);\r
-\r
-      CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
-      RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DefaultNode;\r
-    } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
-      //\r
-      // If RemainingDevicePath isn't the End of Device Path Node,\r
-      // Use the RemainingDevicePath to determine the terminal type\r
-      //\r
-      Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
-      if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
-        TerminalType = PCANSITYPE;\r
-      } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
-        TerminalType = VT100TYPE;\r
-      } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
-        TerminalType = VT100PLUSTYPE;\r
-      } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
-        TerminalType = VTUTF8TYPE;\r
-      } else {\r
-        goto Error;\r
-      }\r
-    } else {\r
-      //\r
-      // If RemainingDevicePath is the End of Device Path Node,\r
-      // skip enumerate any device and return EFI_SUCESSS\r
-      //\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    //\r
-    // Initialize the Terminal Dev\r
-    //\r
-    TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
-    if (TerminalDevice == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto Error;\r
-    }\r
-\r
-    TerminalDevice->TerminalType  = TerminalType;\r
-    TerminalDevice->SerialIo      = SerialIo;\r
-\r
-    InitializeListHead (&TerminalDevice->NotifyList);\r
-    Status = gBS->CreateEvent (\r
-                    EVT_NOTIFY_WAIT,\r
-                    TPL_NOTIFY,\r
-                    TerminalConInWaitForKeyEx,\r
-                    TerminalDevice,\r
-                    &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
-\r
-    Status = gBS->CreateEvent (\r
-                    EVT_NOTIFY_WAIT,\r
-                    TPL_NOTIFY,\r
-                    TerminalConInWaitForKey,\r
-                    TerminalDevice,\r
-                    &TerminalDevice->SimpleInput.WaitForKey\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
-    //\r
-    // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
-    // the pre-read pending characters.\r
-    //\r
-    TerminalDevice->RawFiFo     = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
-    if (TerminalDevice->RawFiFo == NULL) {\r
-      goto Error;\r
-    }\r
-    TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
-    if (TerminalDevice->UnicodeFiFo == NULL) {\r
-      goto Error;\r
-    }\r
-    TerminalDevice->EfiKeyFiFo  = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
-    if (TerminalDevice->EfiKeyFiFo == NULL) {\r
-      goto Error;\r
-    }\r
-\r
-    //\r
-    // Set the timeout value of serial buffer for\r
-    // keystroke response performance issue\r
-    //\r
-    Mode            = TerminalDevice->SerialIo->Mode;\r
+    return Status;\r
+  }\r
 \r
-    SerialInTimeOut = 0;\r
-    if (Mode->BaudRate != 0) {\r
-      SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
-    }\r
+  //\r
+  // Initialize the Terminal Dev\r
+  //\r
+  TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
+  if (TerminalDevice == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto CloseProtocols;\r
+  }\r
 \r
-    Status = TerminalDevice->SerialIo->SetAttributes (\r
-                                        TerminalDevice->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
-    if (EFI_ERROR (Status)) {\r
-      //\r
-      // if set attributes operation fails, invalidate\r
-      // the value of SerialInTimeOut,thus make it\r
-      // inconsistent with the default timeout value\r
-      // of serial buffer. This will invoke the recalculation\r
-      // in the readkeystroke routine.\r
-      //\r
-      TerminalDevice->SerialInTimeOut = 0;\r
-    } else {\r
-      TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
-    }\r
+  if (RemainingDevicePath == NULL) {\r
     //\r
-    // Set Simple Text Output Protocol from template.\r
+    // If RemainingDevicePath is NULL, use default terminal type\r
     //\r
-    SimpleTextOutput = CopyMem (\r
-                         &TerminalDevice->SimpleTextOutput,\r
-                         &mTerminalDevTemplate.SimpleTextOutput,\r
-                         sizeof (mTerminalDevTemplate.SimpleTextOutput)\r
-                         );\r
-    SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
-    \r
-    Status = InitializeTerminalConsoleTextMode (&ModeCount, &TerminalDevice->TerminalConsoleModeData);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
-    TerminalDevice->SimpleTextOutputMode.MaxMode = (INT32) ModeCount;\r
-    \r
+    TerminalDevice->TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
+  } else {\r
     //\r
-    // For terminal devices, cursor is always visible\r
+    // End of Device Path Node is handled in above.\r
     //\r
-    TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
-    Status = TerminalConOutSetAttribute (\r
-               SimpleTextOutput,\r
-               EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
-\r
+    ASSERT (!IsDevicePathEnd (RemainingDevicePath));\r
     //\r
-    // Build the component name for the child device\r
+    // If RemainingDevicePath isn't the End of Device Path Node,\r
+    // Use the RemainingDevicePath to determine the terminal type\r
     //\r
-    TerminalDevice->ControllerNameTable = NULL;\r
-    switch (TerminalDevice->TerminalType) {\r
-    case PCANSITYPE:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"PC-ANSI Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"PC-ANSI Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-\r
-    case VT100TYPE:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100 Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100 Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-\r
-    case VT100PLUSTYPE:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100+ Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-100+ Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-\r
-    case VTUTF8TYPE:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-UTF8 Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"VT-UTF8 Serial Console",\r
-        FALSE\r
-        );\r
+    TerminalDevice->TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *)RemainingDevicePath)->Guid);\r
+  }\r
 \r
-      break;\r
-    }\r
+  ASSERT (TerminalDevice->TerminalType < ARRAY_SIZE (mTerminalType));\r
+  TerminalDevice->SerialIo = SerialIo;\r
 \r
-    //\r
-    // Build the device path for the child device\r
-    //\r
-    Status = SetTerminalDevicePath (\r
-              TerminalDevice->TerminalType,\r
-              ParentDevicePath,\r
-              &TerminalDevice->DevicePath\r
-              );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
-\r
-    Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
+  //\r
+  // Build the component name for the child device\r
+  //\r
+  Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeResources;\r
+  }\r
 \r
-    Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
+  //\r
+  // Build the device path for the child device\r
+  //\r
+  Status = SetTerminalDevicePath (TerminalDevice->TerminalType, ParentDevicePath, &TerminalDevice->DevicePath);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeResources;\r
+  }\r
 \r
-    Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
+  InitializeListHead (&TerminalDevice->NotifyList);\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  TerminalConInWaitForKeyEx,\r
+                  TerminalDevice,\r
+                  &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-    Status = gBS->CreateEvent (\r
-                    EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                    TPL_NOTIFY,\r
-                    TerminalConInTimerHandler,\r
-                    TerminalDevice,\r
-                    &TerminalDevice->TimerEvent\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  TerminalConInWaitForKey,\r
+                  TerminalDevice,\r
+                  &TerminalDevice->SimpleInput.WaitForKey\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  KeyNotifyProcessHandler,\r
+                  TerminalDevice,\r
+                  &TerminalDevice->KeyNotifyProcessEvent\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-    Status = gBS->SetTimer (\r
-                    TerminalDevice->TimerEvent,\r
-                    TimerPeriodic,\r
-                    KEYBOARD_TIMER_INTERVAL\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
+  //\r
+  // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
+  // the pre-read pending characters.\r
+  //\r
+  TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
+  if (TerminalDevice->RawFiFo == NULL) {\r
+    goto FreeResources;\r
+  }\r
 \r
-    Status = gBS->CreateEvent (\r
-                    EVT_TIMER,\r
-                    TPL_CALLBACK,\r
-                    NULL,\r
-                    NULL,\r
-                    &TerminalDevice->TwoSecondTimeOut\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
+  TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
+  if (TerminalDevice->UnicodeFiFo == NULL) {\r
+    goto FreeResources;\r
+  }\r
 \r
-    Status = gBS->InstallProtocolInterface (\r
-                    &TerminalDevice->Handle,\r
-                    &gEfiDevicePathProtocolGuid,\r
-                    EFI_NATIVE_INTERFACE,\r
-                    TerminalDevice->DevicePath\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
+  TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+  if (TerminalDevice->EfiKeyFiFo == NULL) {\r
+    goto FreeResources;\r
+  }\r
 \r
-    //\r
-    // Register the Parent-Child relationship via\r
-    // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    Controller,\r
-                    &gEfiSerialIoProtocolGuid,\r
-                    (VOID **) &TerminalDevice->SerialIo,\r
-                    This->DriverBindingHandle,\r
-                    TerminalDevice->Handle,\r
-                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
+  TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+  if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {\r
+    goto FreeResources;\r
   }\r
 \r
   //\r
-  // Find the child handle, and get its TerminalDevice private data\r
+  // Set the timeout value of serial buffer for keystroke response performance issue\r
   //\r
-  Status = gBS->OpenProtocolInformation (\r
-                  Controller,\r
-                  &gEfiSerialIoProtocolGuid,\r
-                  &OpenInfoBuffer,\r
-                  &EntryCount\r
-                  );\r
-  if (!EFI_ERROR (Status)) {\r
-    Status = EFI_NOT_FOUND;\r
-    ASSERT (OpenInfoBuffer != NULL);\r
-    for (Index = 0; Index < EntryCount; Index++) {\r
-      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
-        //\r
-        // Find the child terminal handle.\r
-        // Test whether the SimpleTxtIn and SimpleTxtOut have been published\r
-        //\r
-        Status = gBS->OpenProtocol (\r
-                        OpenInfoBuffer[Index].ControllerHandle,\r
-                        &gEfiSimpleTextInProtocolGuid,\r
-                        (VOID **) &SimpleTextInput,\r
-                        This->DriverBindingHandle,\r
-                        OpenInfoBuffer[Index].ControllerHandle,\r
-                        EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                        );\r
-        if (!EFI_ERROR (Status)) {\r
-          SimTxtInInstalled = TRUE;\r
-          TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
-        }\r
+  Mode = TerminalDevice->SerialIo->Mode;\r
 \r
-        Status = gBS->OpenProtocol (\r
-                        OpenInfoBuffer[Index].ControllerHandle,\r
-                        &gEfiSimpleTextOutProtocolGuid,\r
-                        (VOID **) &SimpleTextOutput,\r
-                        This->DriverBindingHandle,\r
-                        OpenInfoBuffer[Index].ControllerHandle,\r
-                        EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                        );\r
-        if (!EFI_ERROR (Status)) {\r
-          SimTxtOutInstalled = TRUE;\r
-          TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
-        }\r
-        Status = EFI_SUCCESS;\r
-        break;\r
-      }\r
-    }\r
+  SerialInTimeOut = 0;\r
+  if (Mode->BaudRate != 0) {\r
+    SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN)Mode->BaudRate;\r
+  }\r
 \r
-    FreePool (OpenInfoBuffer);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
+  Status = TerminalDevice->SerialIo->SetAttributes (\r
+                                       TerminalDevice->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
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // if set attributes operation fails, invalidate\r
+    // the value of SerialInTimeOut,thus make it\r
+    // inconsistent with the default timeout value\r
+    // of serial buffer. This will invoke the recalculation\r
+    // in the readkeystroke routine.\r
+    //\r
+    TerminalDevice->SerialInTimeOut = 0;\r
   } else {\r
-    goto ReportError;\r
+    TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
   }\r
 \r
-  ASSERT (TerminalDevice != NULL);\r
+  SimpleTextOutput = &TerminalDevice->SimpleTextOutput;\r
+  SimpleTextInput  = &TerminalDevice->SimpleInput;\r
+\r
   //\r
-  // Only do the reset if the device path is in the Conout variable\r
+  // Initialize SimpleTextOut instance\r
   //\r
-  if (ConInSelected && !SimTxtInInstalled) {\r
-    Status = TerminalDevice->SimpleInput.Reset (\r
-                                          &TerminalDevice->SimpleInput,\r
-                                          FALSE\r
-                                          );\r
-    if (EFI_ERROR (Status)) {\r
-      //\r
-      // Need to report Error Code first\r
-      //\r
-      goto ReportError;\r
-    }\r
+  SimpleTextOutput->Mode                  = &TerminalDevice->SimpleTextOutputMode;\r
+  TerminalDevice->TerminalConsoleModeData = InitializeTerminalConsoleTextMode (\r
+                                              &SimpleTextOutput->Mode->MaxMode\r
+                                              );\r
+  if (TerminalDevice->TerminalConsoleModeData == NULL) {\r
+    goto FreeResources;\r
   }\r
 \r
   //\r
-  // Only output the configure string to remote terminal if the device path\r
-  // is in the Conout variable\r
+  // For terminal devices, cursor is always visible\r
   //\r
-  if (ConOutSelected && !SimTxtOutInstalled) {\r
-    Status = TerminalDevice->SimpleTextOutput.SetAttribute (\r
-                                                        &TerminalDevice->SimpleTextOutput,\r
-                                                        EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
-                                                        );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
-\r
-    Status = TerminalDevice->SimpleTextOutput.Reset (\r
-                                                &TerminalDevice->SimpleTextOutput,\r
-                                                FALSE\r
-                                                );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
-\r
-    Status = TerminalDevice->SimpleTextOutput.SetMode (\r
-                                                &TerminalDevice->SimpleTextOutput,\r
-                                                0\r
-                                                );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
+  SimpleTextOutput->Mode->CursorVisible = TRUE;\r
+  Status                                = SimpleTextOutput->SetAttribute (SimpleTextOutput, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = SimpleTextOutput->Reset (SimpleTextOutput, FALSE);\r
+  }\r
 \r
-    Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
-                                                &TerminalDevice->SimpleTextOutput,\r
-                                                TRUE\r
-                                                );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReportError;\r
   }\r
 \r
   //\r
-  // Simple In/Out Protocol will not be installed onto the handle if the\r
-  // device path to the handle is not present in the ConIn/ConOut\r
-  // environment variable. But If RemainingDevicePath is NULL, then always\r
-  // produce both Simple In and Simple Text Output Protocols. This is required\r
-  // for the connect all sequences to make sure all possible consoles are\r
-  // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
+  // Initialize SimpleTextInput instance\r
   //\r
-  if (!SimTxtInInstalled && (ConInSelected || NullRemaining)) {\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                    &TerminalDevice->Handle,\r
-                    &gEfiSimpleTextInProtocolGuid,\r
-                    &TerminalDevice->SimpleInput,\r
-                    &gEfiSimpleTextInputExProtocolGuid,\r
-                    &TerminalDevice->SimpleInputEx,\r
-                    NULL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
+  Status = SimpleTextInput->Reset (SimpleTextInput, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReportError;\r
   }\r
 \r
-  if (!SimTxtOutInstalled && (ConOutSelected || NullRemaining)) {\r
-    Status = gBS->InstallProtocolInterface (\r
-                    &TerminalDevice->Handle,\r
-                    &gEfiSimpleTextOutProtocolGuid,\r
-                    EFI_NATIVE_INTERFACE,\r
-                    &TerminalDevice->SimpleTextOutput\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &TerminalDevice->Handle,\r
+                  &gEfiSimpleTextInProtocolGuid,\r
+                  &TerminalDevice->SimpleInput,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  &TerminalDevice->SimpleInputEx,\r
+                  &gEfiSimpleTextOutProtocolGuid,\r
+                  &TerminalDevice->SimpleTextOutput,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  TerminalDevice->DevicePath,\r
+                  NULL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiSerialIoProtocolGuid,\r
+                    (VOID **)&TerminalDevice->SerialIo,\r
+                    This->DriverBindingHandle,\r
+                    TerminalDevice->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
                     );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
-    }\r
-  }\r
-  if (DefaultNode != NULL) {\r
-    FreePool (DefaultNode);\r
+    ASSERT_EFI_ERROR (Status);\r
+    StartTerminalStateMachine (TerminalDevice);\r
+    return Status;\r
   }\r
 \r
-  return EFI_SUCCESS;\r
-\r
 ReportError:\r
-  //\r
-  // Report error code before exiting\r
-  //\r
-  DevicePath = ParentDevicePath;\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
-    DevicePath\r
+    ParentDevicePath\r
     );\r
 \r
-Error:\r
-  //\r
-  // Use the Stop() function to free all resources allocated in Start()\r
-  //\r
-  if (TerminalDevice != NULL) {\r
-\r
-    if (TerminalDevice->Handle != NULL) {\r
-      This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
-    } else {\r
-\r
-      if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
-      }\r
+FreeResources:\r
+  ASSERT (TerminalDevice != NULL);\r
 \r
-      if (TerminalDevice->TimerEvent != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->TimerEvent);\r
-      }\r
+  if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
+    gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
+  }\r
 \r
-      if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
-      }\r
+  if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
+    gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+  }\r
 \r
-      if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
-      }\r
+  if (TerminalDevice->KeyNotifyProcessEvent != NULL) {\r
+    gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
+  }\r
 \r
-      TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
+  if (TerminalDevice->RawFiFo != NULL) {\r
+    FreePool (TerminalDevice->RawFiFo);\r
+  }\r
 \r
-      if (TerminalDevice->RawFiFo != NULL) {\r
-        FreePool (TerminalDevice->RawFiFo);\r
-      }\r
-      if (TerminalDevice->UnicodeFiFo != NULL) {\r
-        FreePool (TerminalDevice->UnicodeFiFo);\r
-      }\r
-      if (TerminalDevice->EfiKeyFiFo != NULL) {\r
-        FreePool (TerminalDevice->EfiKeyFiFo);\r
-      }\r
+  if (TerminalDevice->UnicodeFiFo != NULL) {\r
+    FreePool (TerminalDevice->UnicodeFiFo);\r
+  }\r
 \r
-      if (TerminalDevice->ControllerNameTable != NULL) {\r
-        FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
-      }\r
+  if (TerminalDevice->EfiKeyFiFo != NULL) {\r
+    FreePool (TerminalDevice->EfiKeyFiFo);\r
+  }\r
 \r
-      if (TerminalDevice->DevicePath != NULL) {\r
-        FreePool (TerminalDevice->DevicePath);\r
-      }\r
+  if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {\r
+    FreePool (TerminalDevice->EfiKeyFiFoForNotify);\r
+  }\r
 \r
-      if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
-        FreePool (TerminalDevice->TerminalConsoleModeData);\r
-      }\r
+  if (TerminalDevice->ControllerNameTable != NULL) {\r
+    FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
+  }\r
 \r
-      FreePool (TerminalDevice);\r
-    }\r
+  if (TerminalDevice->DevicePath != NULL) {\r
+    FreePool (TerminalDevice->DevicePath);\r
   }\r
 \r
-  if (DefaultNode != NULL) {\r
-    FreePool (DefaultNode);\r
+  if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
+    FreePool (TerminalDevice->TerminalConsoleModeData);\r
   }\r
 \r
-  This->Stop (This, Controller, 0, NULL);\r
+  FreePool (TerminalDevice);\r
+\r
+CloseProtocols:\r
+\r
+  //\r
+  // Remove Parent Device Path from\r
+  // the Console Device Environment Variables\r
+  //\r
+  TerminalRemoveConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);\r
+  TerminalRemoveConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+  TerminalRemoveConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+\r
+  Status = gBS->CloseProtocol (\r
+                  Controller,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  This->DriverBindingHandle,\r
+                  Controller\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
+  Status = gBS->CloseProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  This->DriverBindingHandle,\r
+                  Controller\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
   return Status;\r
 }\r
 \r
@@ -1249,10 +902,10 @@ Error:
 EFI_STATUS\r
 EFIAPI\r
 TerminalDriverBindingStop (\r
-  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
-  IN  EFI_HANDLE                    Controller,\r
-  IN  UINTN                         NumberOfChildren,\r
-  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   Controller,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
   )\r
 {\r
   EFI_STATUS                       Status;\r
@@ -1262,16 +915,6 @@ TerminalDriverBindingStop (
   TERMINAL_DEV                     *TerminalDevice;\r
   EFI_DEVICE_PATH_PROTOCOL         *ParentDevicePath;\r
   EFI_SERIAL_IO_PROTOCOL           *SerialIo;\r
-  EFI_DEVICE_PATH_PROTOCOL         *DevicePath;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &DevicePath\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
 \r
   //\r
   // Complete all outstanding transactions to Controller.\r
@@ -1283,52 +926,35 @@ TerminalDriverBindingStop (
     //\r
     Status = gBS->OpenProtocol (\r
                     Controller,\r
-                    &gEfiCallerIdGuid,\r
-                    (VOID **) &ParentDevicePath,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    (VOID **)&ParentDevicePath,\r
                     This->DriverBindingHandle,\r
                     Controller,\r
                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                     );\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Remove Parent Device Path from\r
-      // the Console Device Environment Variables\r
-      //\r
-      TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
-      TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
-      TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
-\r
-      //\r
-      // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
-      //\r
-      Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                      Controller,\r
-                      &gEfiCallerIdGuid,\r
-                      ParentDevicePath,\r
-                      NULL\r
-                      );\r
+    ASSERT_EFI_ERROR (Status);\r
 \r
-      //\r
-      // Free the ParentDevicePath that was duplicated in Start()\r
-      //\r
-      if (!EFI_ERROR (Status)) {\r
-        FreePool (ParentDevicePath);\r
-      }\r
-    }\r
+    //\r
+    // Remove Parent Device Path from\r
+    // the Console Device Environment Variables\r
+    //\r
+    TerminalRemoveConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);\r
+    TerminalRemoveConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
+    TerminalRemoveConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);\r
 \r
     gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiSerialIoProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
+           Controller,\r
+           &gEfiSerialIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
 \r
     gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiDevicePathProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
+           Controller,\r
+           &gEfiDevicePathProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
 \r
     return EFI_SUCCESS;\r
   }\r
@@ -1336,25 +962,23 @@ TerminalDriverBindingStop (
   AllChildrenStopped = TRUE;\r
 \r
   for (Index = 0; Index < NumberOfChildren; Index++) {\r
-\r
     Status = gBS->OpenProtocol (\r
                     ChildHandleBuffer[Index],\r
                     &gEfiSimpleTextOutProtocolGuid,\r
-                    (VOID **) &SimpleTextOutput,\r
+                    (VOID **)&SimpleTextOutput,\r
                     This->DriverBindingHandle,\r
                     ChildHandleBuffer[Index],\r
                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                     );\r
     if (!EFI_ERROR (Status)) {\r
-\r
       TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
 \r
       gBS->CloseProtocol (\r
-            Controller,\r
-            &gEfiSerialIoProtocolGuid,\r
-            This->DriverBindingHandle,\r
-            ChildHandleBuffer[Index]\r
-            );\r
+             Controller,\r
+             &gEfiSerialIoProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             ChildHandleBuffer[Index]\r
+             );\r
 \r
       Status = gBS->UninstallMultipleProtocolInterfaces (\r
                       ChildHandleBuffer[Index],\r
@@ -1370,28 +994,22 @@ TerminalDriverBindingStop (
                       );\r
       if (EFI_ERROR (Status)) {\r
         gBS->OpenProtocol (\r
-              Controller,\r
-              &gEfiSerialIoProtocolGuid,\r
-              (VOID **) &SerialIo,\r
-              This->DriverBindingHandle,\r
-              ChildHandleBuffer[Index],\r
-              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-              );\r
+               Controller,\r
+               &gEfiSerialIoProtocolGuid,\r
+               (VOID **)&SerialIo,\r
+               This->DriverBindingHandle,\r
+               ChildHandleBuffer[Index],\r
+               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+               );\r
       } else {\r
-\r
-        if (TerminalDevice->ControllerNameTable != NULL) {\r
-          FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
-        }\r
-\r
-        gBS->CloseEvent (TerminalDevice->TimerEvent);\r
-        gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
+        FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
+        StopTerminalStateMachine (TerminalDevice);\r
         gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
         gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+        gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
         TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
         FreePool (TerminalDevice->DevicePath);\r
-        if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
-          FreePool (TerminalDevice->TerminalConsoleModeData);\r
-        }\r
+        FreePool (TerminalDevice->TerminalConsoleModeData);\r
         FreePool (TerminalDevice);\r
       }\r
     }\r
@@ -1408,6 +1026,49 @@ TerminalDriverBindingStop (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Compare a device path data structure to that of all the nodes of a\r
+  second device path instance.\r
+\r
+  @param  Multi          A pointer to a multi-instance device path data structure.\r
+  @param  Single         A pointer to a single-instance device path data structure.\r
+\r
+  @retval TRUE           If the Single is contained within Multi.\r
+  @retval FALSE          The Single is not match within Multi.\r
+\r
+**/\r
+BOOLEAN\r
+MatchDevicePaths (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  UINTN                     Size;\r
+\r
+  DevicePath     = Multi;\r
+  DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+  //\r
+  // Search for the match of 'Single' in 'Multi'\r
+  //\r
+  while (DevicePathInst != NULL) {\r
+    //\r
+    // If the single device path is found in multiple device paths,\r
+    // return success\r
+    //\r
+    if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+      FreePool (DevicePathInst);\r
+      return TRUE;\r
+    }\r
+\r
+    FreePool (DevicePathInst);\r
+    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Update terminal device path in Console Device Environment Variables.\r
 \r
@@ -1421,38 +1082,48 @@ TerminalUpdateConsoleDevVariable (
   IN EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath\r
   )\r
 {\r
-  EFI_STATUS                Status;\r
-  UINTN                     NameSize;\r
-  UINTN                     VariableSize;\r
-  UINT8                     TerminalType;\r
-  EFI_DEVICE_PATH_PROTOCOL  *Variable;\r
-  EFI_DEVICE_PATH_PROTOCOL  *NewVariable;\r
-  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
-  EDKII_SET_VARIABLE_STATUS *SetVariableStatus;\r
+  EFI_STATUS                 Status;\r
+  UINTN                      NameSize;\r
+  UINTN                      VariableSize;\r
+  TERMINAL_TYPE              TerminalType;\r
+  EFI_DEVICE_PATH_PROTOCOL   *Variable;\r
+  EFI_DEVICE_PATH_PROTOCOL   *NewVariable;\r
+  EFI_DEVICE_PATH_PROTOCOL   *TempDevicePath;\r
+  EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;\r
 \r
   //\r
   // Get global variable and its size according to the name given.\r
   //\r
-  GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
-  if (Variable == NULL) {\r
+  Status = GetEfiGlobalVariable2 (VariableName, (VOID **)&Variable, NULL);\r
+  if (Status == EFI_NOT_FOUND) {\r
+    Status   = EFI_SUCCESS;\r
+    Variable = NULL;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
     return;\r
   }\r
 \r
   //\r
   // Append terminal device path onto the variable.\r
   //\r
-  for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
+  for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
     SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
-    NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
-    if (Variable != NULL) {\r
-      FreePool (Variable);\r
-    }\r
 \r
     if (TempDevicePath != NULL) {\r
+      if (!MatchDevicePaths (Variable, TempDevicePath)) {\r
+        NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
+        if (NewVariable != NULL) {\r
+          if (Variable != NULL) {\r
+            FreePool (Variable);\r
+          }\r
+\r
+          Variable = NewVariable;\r
+        }\r
+      }\r
+\r
       FreePool (TempDevicePath);\r
     }\r
-\r
-    Variable = NewVariable;\r
   }\r
 \r
   VariableSize = GetDevicePathSize (Variable);\r
@@ -1466,7 +1137,7 @@ TerminalUpdateConsoleDevVariable (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    NameSize = StrSize (VariableName);\r
+    NameSize          = StrSize (VariableName);\r
     SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize);\r
     if (SetVariableStatus != NULL) {\r
       CopyGuid (&SetVariableStatus->Guid, &gEfiGlobalVariableGuid);\r
@@ -1474,8 +1145,8 @@ TerminalUpdateConsoleDevVariable (
       SetVariableStatus->DataSize   = VariableSize;\r
       SetVariableStatus->SetStatus  = Status;\r
       SetVariableStatus->Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
-      CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);\r
-      CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Variable,     VariableSize);\r
+      CopyMem (SetVariableStatus + 1, VariableName, NameSize);\r
+      CopyMem (((UINT8 *)(SetVariableStatus + 1)) + NameSize, Variable, VariableSize);\r
 \r
       REPORT_STATUS_CODE_EX (\r
         EFI_ERROR_CODE,\r
@@ -1493,10 +1164,9 @@ TerminalUpdateConsoleDevVariable (
 \r
   FreePool (Variable);\r
 \r
-  return ;\r
+  return;\r
 }\r
 \r
-\r
 /**\r
   Remove terminal device path from Console Device Environment Variables.\r
 \r
@@ -1515,7 +1185,7 @@ TerminalRemoveConsoleDevVariable (
   BOOLEAN                   Match;\r
   UINTN                     VariableSize;\r
   UINTN                     InstanceSize;\r
-  UINT8                     TerminalType;\r
+  TERMINAL_TYPE             TerminalType;\r
   EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
   EFI_DEVICE_PATH_PROTOCOL  *Variable;\r
   EFI_DEVICE_PATH_PROTOCOL  *OriginalVariable;\r
@@ -1523,19 +1193,19 @@ TerminalRemoveConsoleDevVariable (
   EFI_DEVICE_PATH_PROTOCOL  *SavedNewVariable;\r
   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
 \r
-  Instance  = NULL;\r
+  Instance = NULL;\r
 \r
   //\r
   // Get global variable and its size according to the name given.\r
   //\r
-  GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
+  GetEfiGlobalVariable2 (VariableName, (VOID **)&Variable, NULL);\r
   if (Variable == NULL) {\r
-    return ;\r
+    return;\r
   }\r
 \r
-  FoundOne          = FALSE;\r
-  OriginalVariable  = Variable;\r
-  NewVariable       = NULL;\r
+  FoundOne         = FALSE;\r
+  OriginalVariable = Variable;\r
+  NewVariable      = NULL;\r
 \r
   //\r
   // Get first device path instance from Variable\r
@@ -1543,8 +1213,9 @@ TerminalRemoveConsoleDevVariable (
   Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
   if (Instance == NULL) {\r
     FreePool (OriginalVariable);\r
-    return ;\r
+    return;\r
   }\r
+\r
   //\r
   // Loop through all the device path instances of Variable\r
   //\r
@@ -1553,8 +1224,7 @@ TerminalRemoveConsoleDevVariable (
     // Loop through all the terminal types that this driver supports\r
     //\r
     Match = FALSE;\r
-    for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
-\r
+    for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
       SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
 \r
       //\r
@@ -1562,23 +1232,25 @@ TerminalRemoveConsoleDevVariable (
       //\r
       if (TempDevicePath != NULL) {\r
         if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
-          Match     = TRUE;\r
-          FoundOne  = TRUE;\r
+          Match    = TRUE;\r
+          FoundOne = TRUE;\r
         }\r
 \r
         FreePool (TempDevicePath);\r
       }\r
     }\r
+\r
     //\r
     // If a match was not found, then keep the current device path instance\r
     //\r
     if (!Match) {\r
-      SavedNewVariable  = NewVariable;\r
-      NewVariable       = AppendDevicePathInstance (NewVariable, Instance);\r
+      SavedNewVariable = NewVariable;\r
+      NewVariable      = AppendDevicePathInstance (NewVariable, Instance);\r
       if (SavedNewVariable != NULL) {\r
         FreePool (SavedNewVariable);\r
       }\r
     }\r
+\r
     //\r
     // Get next device path instance from Variable\r
     //\r
@@ -1608,7 +1280,7 @@ TerminalRemoveConsoleDevVariable (
     FreePool (NewVariable);\r
   }\r
 \r
-  return ;\r
+  return;\r
 }\r
 \r
 /**\r
@@ -1625,49 +1297,18 @@ TerminalRemoveConsoleDevVariable (
 **/\r
 EFI_STATUS\r
 SetTerminalDevicePath (\r
-  IN  UINT8                       TerminalType,\r
-  IN  EFI_DEVICE_PATH_PROTOCOL    *ParentDevicePath,\r
-  OUT EFI_DEVICE_PATH_PROTOCOL    **TerminalDevicePath\r
+  IN  TERMINAL_TYPE             TerminalType,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL  **TerminalDevicePath\r
   )\r
 {\r
   VENDOR_DEVICE_PATH  Node;\r
 \r
-  *TerminalDevicePath = NULL;\r
+  ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
   Node.Header.Type    = MESSAGING_DEVICE_PATH;\r
   Node.Header.SubType = MSG_VENDOR_DP;\r
-\r
-  //\r
-  // Generate terminal device path node according to terminal type.\r
-  //\r
-  switch (TerminalType) {\r
-\r
-  case PCANSITYPE:\r
-    CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
-    break;\r
-\r
-  case VT100TYPE:\r
-    CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
-    break;\r
-\r
-  case VT100PLUSTYPE:\r
-    CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
-    break;\r
-\r
-  case VTUTF8TYPE:\r
-    CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
-    break;\r
-\r
-  default:\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  //\r
-  // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
-  //\r
-  SetDevicePathNodeLength (\r
-    &Node.Header,\r
-    sizeof (VENDOR_DEVICE_PATH)\r
-    );\r
+  SetDevicePathNodeLength (&Node.Header, sizeof (VENDOR_DEVICE_PATH));\r
+  CopyGuid (&Node.Guid, mTerminalType[TerminalType]);\r
 \r
   //\r
   // Append the terminal node onto parent device path\r
@@ -1675,7 +1316,7 @@ SetTerminalDevicePath (
   //\r
   *TerminalDevicePath = AppendDevicePathNode (\r
                           ParentDevicePath,\r
-                          (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
+                          (EFI_DEVICE_PATH_PROTOCOL *)&Node\r
                           );\r
   if (*TerminalDevicePath == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -1696,12 +1337,12 @@ SetTerminalDevicePath (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-InitializeTerminal(\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
+InitializeTerminal (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
+  EFI_STATUS  Status;\r
 \r
   //\r
   // Install driver model protocol(s).\r
@@ -1733,10 +1374,10 @@ InitializeTerminal(
 **/\r
 BOOLEAN\r
 IsHotPlugDevice (\r
-  IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
   )\r
 {\r
-  EFI_DEVICE_PATH_PROTOCOL     *CheckDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CheckDevicePath;\r
 \r
   CheckDevicePath = DevicePath;\r
   while (!IsDevicePathEnd (CheckDevicePath)) {\r
@@ -1744,16 +1385,19 @@ IsHotPlugDevice (
     // Check device whether is hot plug device or not throught Device Path\r
     //\r
     if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
-        (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
-         DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
-         DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
+        ((DevicePathSubType (CheckDevicePath) == MSG_USB_DP) ||\r
+         (DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP) ||\r
+         (DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)))\r
+    {\r
       //\r
       // If Device is USB device\r
       //\r
       return TRUE;\r
     }\r
+\r
     if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
-        (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
+        (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP))\r
+    {\r
       //\r
       // If Device is PCCard\r
       //\r
@@ -1765,4 +1409,3 @@ IsHotPlugDevice (
 \r
   return FALSE;\r
 }\r
-\r