]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
MdeModulePkg/TerminalDxe: Avoid always append device path to *Dev
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / Terminal.c
index 6fde3b2c7aa9c337c8b560bfd753c31386671fe1..60de2d4d6db2b09f8937226465ca98e9c2660d21 100644 (file)
@@ -2,7 +2,7 @@
   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
+Copyright (c) 2006 - 2017, 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
@@ -29,7 +29,7 @@ EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {
 };\r
 \r
 \r
-EFI_GUID  *gTerminalType[] = {\r
+EFI_GUID  *mTerminalType[] = {\r
   &gEfiPcAnsiGuid,\r
   &gEfiVT100Guid,\r
   &gEfiVT100PlusGuid,\r
@@ -38,6 +38,14 @@ EFI_GUID  *gTerminalType[] = {
 };\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
+};\r
+\r
 TERMINAL_DEV  mTerminalDevTemplate = {\r
   TERMINAL_DEV_SIGNATURE,\r
   NULL,\r
@@ -75,6 +83,7 @@ TERMINAL_DEV  mTerminalDevTemplate = {
   NULL, // RawFifo\r
   NULL, // UnicodeFiFo\r
   NULL, // EfiKeyFiFo\r
+  NULL, // EfiKeyFiFoForNotify\r
 \r
   NULL, // ControllerNameTable\r
   NULL, // TimerEvent\r
@@ -99,16 +108,41 @@ TERMINAL_DEV  mTerminalDevTemplate = {
   {   // NotifyList\r
     NULL,\r
     NULL,\r
-  }\r
+  },\r
+  NULL // KeyNotifyProcessEvent\r
 };\r
 \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
+  return Type;\r
+}\r
+\r
 /**\r
   Test to see if this driver supports Controller.\r
 \r
@@ -161,12 +195,7 @@ TerminalDriverBindingSupported (
       //\r
       // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm 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
-          !CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-\r
+      if (TerminalTypeFromGuid (&Node->Guid) == ARRAY_SIZE (mTerminalType)) {\r
         return EFI_UNSUPPORTED;\r
       }\r
     }\r
@@ -235,154 +264,6 @@ TerminalDriverBindingSupported (
   return Status;\r
 }\r
 \r
-/**\r
-  Build the terminal device path for the child device according to the\r
-  terminal type.\r
-\r
-  @param  ParentDevicePath         Parent device path.\r
-  @param  RemainingDevicePath      A specific child device.\r
-\r
-  @return The child device path built.\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
-  )\r
-{\r
-  EFI_DEVICE_PATH_PROTOCOL          *TerminalDevicePath;\r
-  UINT8                             TerminalType;\r
-  VENDOR_DEVICE_PATH                *Node;\r
-  EFI_STATUS                        Status;\r
-\r
-  TerminalDevicePath = NULL;\r
-\r
-  //\r
-  // Use the RemainingDevicePath to determine the terminal type\r
-  //\r
-  Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
-  if (Node == NULL) {\r
-    TerminalType = PcdGet8 (PcdDefaultTerminalType);\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
-\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 if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-\r
-    TerminalType = TTYTERMTYPE;\r
-\r
-  } else {\r
-    return NULL;\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
-  }\r
-  return TerminalDevicePath;\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
-  Check whether the terminal device path is in the global variable.\r
-\r
-  @param  VariableName          Pointer to one global variable.\r
-  @param  TerminalDevicePath    Pointer to the terminal device's device path.\r
-\r
-  @retval TRUE                  The devcie is in the global variable.\r
-  @retval FALSE                 The devcie is not in the global variable.\r
-\r
-**/\r
-BOOLEAN\r
-IsTerminalInConsoleVariable (\r
-  IN CHAR16                    *VariableName,\r
-  IN EFI_DEVICE_PATH_PROTOCOL  *TerminalDevicePath\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
-\r
-  //\r
-  // Check whether the terminal device path is one of the variable instances.\r
-  //\r
-  ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
-\r
-  FreePool (Variable);\r
-\r
-  return ReturnFlag;\r
-}\r
 \r
 /**\r
   Free notify functions list.\r
@@ -423,97 +304,136 @@ TerminalFreeNotifyList (
   It returns information for available text modes that the terminal can support.\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
+  @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
-EFI_STATUS\r
+TERMINAL_CONSOLE_MODE_DATA *\r
 InitializeTerminalConsoleTextMode (\r
-  OUT UINTN                         *TextModeCount,\r
-  OUT TERMINAL_CONSOLE_MODE_DATA    **TextModeData\r
-  )\r
+  OUT INT32                         *TextModeCount\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
-  }\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
+  TERMINAL_CONSOLE_MODE_DATA  *TextModeData;\r
 \r
-  //\r
-  // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
-  //\r
-  ValidCount = 0;  \r
+  ASSERT (TextModeCount != NULL);\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
+  TextModeData = AllocateCopyPool (sizeof (mTerminalConsoleModeData), mTerminalConsoleModeData);\r
+  if (TextModeData == NULL) {\r
+    return NULL;\r
   }\r
\r
+  *TextModeCount = ARRAY_SIZE (mTerminalConsoleModeData);\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
+    INT32 Index;\r
+    for (Index = 0; Index < *TextModeCount; Index++) {\r
+      DEBUG ((DEBUG_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n",\r
+              Index, TextModeData[Index].Columns, TextModeData[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
+  return TextModeData;\r
+}\r
+\r
+/**\r
+  Stop the terminal state machine.\r
+\r
+  @param TerminalDevice    The terminal device.\r
+**/\r
+VOID\r
+StopTerminalStateMachine (\r
+  TERMINAL_DEV             *TerminalDevice\r
+  )\r
+{\r
+  EFI_TPL                  OriginalTpl;\r
+\r
+  OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  gBS->CloseEvent (TerminalDevice->TimerEvent);\r
+  gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
+\r
+  gBS->RestoreTPL (OriginalTpl);\r
+}\r
+\r
+/**\r
+  Start the terminal state machine.\r
+\r
+  @param TerminalDevice    The terminal device.\r
+**/\r
+VOID\r
+StartTerminalStateMachine (\r
+  TERMINAL_DEV             *TerminalDevice\r
+  )\r
+{\r
+  EFI_STATUS               Status;\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
+  Status = gBS->SetTimer (\r
+                  TerminalDevice->TimerEvent,\r
+                  TimerPeriodic,\r
+                  KEYBOARD_TIMER_INTERVAL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\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
+}\r
+\r
+/**\r
+  Initialize the controller name table.\r
+\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
+InitializeControllerNameTable (\r
+  TERMINAL_TYPE             TerminalType,\r
+  EFI_UNICODE_STRING_TABLE  **ControllerNameTable\r
+)\r
+{\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
+  if (!EFI_ERROR (Status)) {\r
+    *ControllerNameTable = Table;\r
+  }\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -543,7 +463,8 @@ TerminalDriverBindingStart (
   EFI_STATUS                          Status;\r
   EFI_SERIAL_IO_PROTOCOL              *SerialIo;\r
   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;\r
-  VENDOR_DEVICE_PATH                  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL            *Vendor;\r
+  EFI_HANDLE                          SerialIoHandle;\r
   EFI_SERIAL_IO_MODE                  *Mode;\r
   UINTN                               SerialInTimeOut;\r
   TERMINAL_DEV                        *TerminalDevice;\r
@@ -551,24 +472,10 @@ TerminalDriverBindingStart (
   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
-  ConInSelected      = FALSE;\r
-  ConOutSelected     = FALSE;\r
-  NullRemaining      = FALSE;\r
-  SimTxtInInstalled  = FALSE;\r
-  SimTxtOutInstalled = FALSE;\r
-  FirstEnter         = FALSE;\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
@@ -580,9 +487,7 @@ TerminalDriverBindingStart (
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
-    return Status;\r
-  }\r
+  ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));\r
 \r
   //\r
   // Open the Serial I/O Protocol BY_DRIVER.  It might already be started.\r
@@ -595,652 +500,351 @@ TerminalDriverBindingStart (
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
-    return Status;\r
-  }\r
+  ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));\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
-  }\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
-  //\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
-\r
-    if (!IsHotPlugDevice (ParentDevicePath)) {\r
-      //\r
-      // if the serial device is a hot plug device, do not update the\r
-      // ConInDev, ConOutDev, and StdErrDev variables.\r
-      //\r
-      TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
-      TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
-      TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\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
+    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
-  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
+  // Do not create any child for END remaining device path.\r
   //\r
-  if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
-    goto Error;\r
+  if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {\r
+    return EFI_SUCCESS;\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
-    //\r
-    Status = gBS->OpenProtocolInformation (\r
-                    Controller,\r
-                    &gEfiSerialIoProtocolGuid,\r
-                    &OpenInfoBuffer,\r
-                    &EntryCount\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      Status = EFI_SUCCESS;\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
-        }\r
-      }\r
-\r
-      FreePool (OpenInfoBuffer);\r
-      if (EFI_ERROR (Status)) {\r
-          goto Error;\r
-      }\r
-    }\r
-\r
-    //\r
-    // If RemainingDevicePath is NULL, use default terminal type\r
-    //\r
-    if (RemainingDevicePath == NULL) {\r
-      TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
-      //\r
-      // Must be between PCANSITYPE (0) and TTYTERMTYPE (4)\r
-      //\r
-      ASSERT (TerminalType <= TTYTERMTYPE);\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 if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
-        TerminalType = TTYTERMTYPE;\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
-\r
-    SerialInTimeOut = 0;\r
-    if (Mode->BaudRate != 0) {\r
-      SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\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
-    //\r
-    // Set Simple Text Output Protocol from template.\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
-    //\r
-    // For terminal devices, cursor is always visible\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
-    //\r
-    // Build the component name for the child device\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
-\r
-      break;\r
-\r
-    case TTYTERMTYPE:\r
-      AddUnicodeString2 (\r
-        "eng",\r
-        gTerminalComponentName.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"Tty Terminal Serial Console",\r
-        TRUE\r
-        );\r
-      AddUnicodeString2 (\r
-        "en",\r
-        gTerminalComponentName2.SupportedLanguages,\r
-        &TerminalDevice->ControllerNameTable,\r
-        (CHAR16 *)L"Tty Terminal Serial Console",\r
-        FALSE\r
-        );\r
-\r
-      break;\r
-    }\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
-    Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
-\r
-    Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\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
-    Status = gBS->SetTimer (\r
-                    TerminalDevice->TimerEvent,\r
-                    TimerPeriodic,\r
-                    KEYBOARD_TIMER_INTERVAL\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\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
+  if (Status == EFI_ALREADY_STARTED) {\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
+    if (RemainingDevicePath == NULL) {\r
+      //\r
+      // If RemainingDevicePath is NULL or is the End of Device Path Node\r
+      //\r
+      return EFI_SUCCESS;\r
     }\r
 \r
     //\r
-    // Register the Parent-Child relationship via\r
-    // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\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->OpenProtocol (\r
+    Status = gBS->OpenProtocolInformation (\r
                     Controller,\r
                     &gEfiSerialIoProtocolGuid,\r
-                    (VOID **) &TerminalDevice->SerialIo,\r
-                    This->DriverBindingHandle,\r
-                    TerminalDevice->Handle,\r
-                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    &OpenInfoBuffer,\r
+                    &EntryCount\r
                     );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\r
+    if (!EFI_ERROR (Status)) {\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 = 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
+          break;\r
+        }\r
+      }\r
+      FreePool (OpenInfoBuffer);\r
     }\r
+    return Status;\r
   }\r
 \r
   //\r
-  // Find the child handle, and get its TerminalDevice private data\r
+  // Initialize the Terminal Dev\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
-\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
+  TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
+  if (TerminalDevice == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto CloseProtocols;\r
+  }\r
 \r
-    FreePool (OpenInfoBuffer);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\r
+  if (RemainingDevicePath == NULL) {\r
+    //\r
+    // If RemainingDevicePath is NULL, use default terminal type\r
+    //\r
+    TerminalDevice->TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
   } else {\r
-    goto ReportError;\r
+    //\r
+    // End of Device Path Node is handled in above.\r
+    //\r
+    ASSERT (!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
+    TerminalDevice->TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid);\r
   }\r
+  ASSERT (TerminalDevice->TerminalType < ARRAY_SIZE (mTerminalType));\r
+  TerminalDevice->SerialIo = SerialIo;\r
 \r
-  ASSERT (TerminalDevice != NULL);\r
   //\r
-  // Only do the reset if the device path is in the Conout variable\r
+  // Build the component name for the child device\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
+  Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
+  if (EFI_ERROR (Status)) {\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
+  // Build the device path for the child device\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
+  Status = SetTerminalDevicePath (TerminalDevice->TerminalType, ParentDevicePath, &TerminalDevice->DevicePath);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeResources;\r
+  }\r
 \r
-    Status = TerminalDevice->SimpleTextOutput.Reset (\r
-                                                &TerminalDevice->SimpleTextOutput,\r
-                                                FALSE\r
-                                                );\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 = TerminalDevice->SimpleTextOutput.SetMode (\r
-                                                &TerminalDevice->SimpleTextOutput,\r
-                                                0\r
-                                                );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\r
-    }\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 = TerminalDevice->SimpleTextOutput.EnableCursor (\r
-                                                &TerminalDevice->SimpleTextOutput,\r
-                                                TRUE\r
-                                                );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ReportError;\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 FreeResources;\r
+  }\r
+  TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
+  if (TerminalDevice->UnicodeFiFo == NULL) {\r
+    goto FreeResources;\r
+  }\r
+  TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+  if (TerminalDevice->EfiKeyFiFo == NULL) {\r
+    goto FreeResources;\r
+  }\r
+  TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+  if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {\r
+    goto FreeResources;\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
+  // Set the timeout value of serial buffer for keystroke response performance issue\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
+  Mode = TerminalDevice->SerialIo->Mode;\r
+\r
+  SerialInTimeOut = 0;\r
+  if (Mode->BaudRate != 0) {\r
+    SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
   }\r
 \r
-  if (!SimTxtOutInstalled && (ConOutSelected || NullRemaining)) {\r
-    Status = gBS->InstallProtocolInterface (\r
-                    &TerminalDevice->Handle,\r
-                    &gEfiSimpleTextOutProtocolGuid,\r
-                    EFI_NATIVE_INTERFACE,\r
-                    &TerminalDevice->SimpleTextOutput\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error;\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
 \r
-  return EFI_SUCCESS;\r
+  SimpleTextOutput = &TerminalDevice->SimpleTextOutput;\r
+  SimpleTextInput = &TerminalDevice->SimpleInput;\r
 \r
-ReportError:\r
   //\r
-  // Report error code before exiting\r
+  // Initialize SimpleTextOut instance\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
-    );\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
+  // For terminal devices, cursor is always visible\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
+  if (EFI_ERROR (Status)) {\r
+    goto ReportError;\r
+  }\r
 \r
-Error:\r
   //\r
-  // Use the Stop() function to free all resources allocated in Start()\r
+  // Initialize SimpleTextInput instance\r
   //\r
-  if (TerminalDevice != NULL) {\r
+  Status = SimpleTextInput->Reset (SimpleTextInput, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReportError;\r
+  }\r
 \r
-    if (TerminalDevice->Handle != NULL) {\r
-      This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
-    } else {\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &TerminalDevice->Handle,\r
+                  &gEfiSimpleTextInProtocolGuid,      &TerminalDevice->SimpleInput,\r
+                  &gEfiSimpleTextInputExProtocolGuid, &TerminalDevice->SimpleInputEx,\r
+                  &gEfiSimpleTextOutProtocolGuid,     &TerminalDevice->SimpleTextOutput,\r
+                  &gEfiDevicePathProtocolGuid,        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
+    ASSERT_EFI_ERROR (Status);\r
+    StartTerminalStateMachine (TerminalDevice);\r
+    return Status;\r
+  }\r
 \r
-      if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
-      }\r
+ReportError:\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
+    ParentDevicePath\r
+    );\r
 \r
-      if (TerminalDevice->TimerEvent != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->TimerEvent);\r
-      }\r
+FreeResources:\r
+  ASSERT (TerminalDevice != NULL);\r
 \r
-      if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\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
+  if (TerminalDevice->KeyNotifyProcessEvent != NULL) {\r
+    gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
+  }\r
 \r
-      if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
-        gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\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->EfiKeyFiFoForNotify != NULL) {\r
+    FreePool (TerminalDevice->EfiKeyFiFoForNotify);\r
+  }\r
 \r
-      TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
+  if (TerminalDevice->ControllerNameTable != NULL) {\r
+    FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\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->DevicePath != NULL) {\r
+    FreePool (TerminalDevice->DevicePath);\r
+  }\r
 \r
-      if (TerminalDevice->ControllerNameTable != NULL) {\r
-        FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
-      }\r
+  if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
+    FreePool (TerminalDevice->TerminalConsoleModeData);\r
+  }\r
 \r
-      if (TerminalDevice->DevicePath != NULL) {\r
-        FreePool (TerminalDevice->DevicePath);\r
-      }\r
+  FreePool (TerminalDevice);\r
 \r
-      if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
-        FreePool (TerminalDevice->TerminalConsoleModeData);\r
-      }\r
+CloseProtocols:\r
 \r
-      FreePool (TerminalDevice);\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
-  This->Stop (This, Controller, 0, NULL);\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
@@ -1275,16 +879,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
@@ -1296,38 +890,21 @@ TerminalDriverBindingStop (
     //\r
     Status = gBS->OpenProtocol (\r
                     Controller,\r
-                    &gEfiCallerIdGuid,\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
@@ -1392,19 +969,14 @@ TerminalDriverBindingStop (
               );\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
@@ -1421,6 +993,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
@@ -1437,7 +1052,7 @@ TerminalUpdateConsoleDevVariable (
   EFI_STATUS                Status;\r
   UINTN                     NameSize;\r
   UINTN                     VariableSize;\r
-  UINT8                     TerminalType;\r
+  TERMINAL_TYPE             TerminalType;\r
   EFI_DEVICE_PATH_PROTOCOL  *Variable;\r
   EFI_DEVICE_PATH_PROTOCOL  *NewVariable;\r
   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
@@ -1446,27 +1061,35 @@ TerminalUpdateConsoleDevVariable (
   //\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
+  if (EFI_ERROR (Status)) {\r
     return;\r
   }\r
 \r
   //\r
   // Append terminal device path onto the variable.\r
   //\r
-  for (TerminalType = PCANSITYPE; TerminalType <= TTYTERMTYPE; TerminalType++) {\r
+  for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
     SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
-    NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
-    ASSERT (NewVariable != NULL);\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
+          Variable = NewVariable;\r
+        }\r
+      }\r
+\r
       FreePool (TempDevicePath);\r
     }\r
 \r
-    Variable = NewVariable;\r
   }\r
 \r
   VariableSize = GetDevicePathSize (Variable);\r
@@ -1529,7 +1152,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
@@ -1567,7 +1190,7 @@ TerminalRemoveConsoleDevVariable (
     // Loop through all the terminal types that this driver supports\r
     //\r
     Match = FALSE;\r
-    for (TerminalType = PCANSITYPE; TerminalType <= TTYTERMTYPE; TerminalType++) {\r
+    for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
 \r
       SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
 \r
@@ -1639,53 +1262,18 @@ TerminalRemoveConsoleDevVariable (
 **/\r
 EFI_STATUS\r
 SetTerminalDevicePath (\r
-  IN  UINT8                       TerminalType,\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
-  case TTYTERMTYPE:\r
-    CopyGuid (&Node.Guid, &gEfiTtyTermGuid);\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