]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
Remove unnecessary use of FixedPcdxxx() functions and [FixedPcd] INF sections. These...
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / Terminal.c
index 5e3b689a18ccb2a9a7b2e84c6984b68399d7ed37..0ae261f019bc4d38c15147e998c118ebba039e5c 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 - 2008, Intel Corporation. <BR>\r
+Copyright (c) 2006 - 2010, Intel Corporation. <BR>\r
 All rights reserved. This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -124,34 +124,46 @@ TerminalDriverBindingSupported (
   // device path that describes a terminal communications protocol.\r
   //\r
   if (RemainingDevicePath != NULL) {\r
+    //\r
+    // Check if RemainingDevicePath is the End of Device Path Node,\r
+    // if yes, go on checking other conditions\r
+    //\r
+    if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // If RemainingDevicePath isn't the End of Device Path Node,\r
+      // check its validation\r
+      //\r
+      Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\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
+      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
+        return EFI_UNSUPPORTED;\r
 \r
-    }\r
-    //\r
-    // only supports PC ANSI, VT100, VT100+ and VT-UTF8 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
+      //\r
+      // only supports PC ANSI, VT100, VT100+ and VT-UTF8 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
-      return EFI_UNSUPPORTED;\r
+        return EFI_UNSUPPORTED;\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
+  // This driver is a bus driver with at most 1 child device, so it is\r
+  // ok for it to be already started.\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  (VOID **) &SerialIo,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -164,22 +176,23 @@ TerminalDriverBindingSupported (
     return Status;\r
   }\r
 \r
+  //\r
+  // Close the I/O Abstraction(s) used to perform the supported test\r
+  //\r
   gBS->CloseProtocol (\r
         Controller,\r
-        &gEfiDevicePathProtocolGuid,\r
+        &gEfiSerialIoProtocolGuid,\r
         This->DriverBindingHandle,\r
         Controller\r
         );\r
 \r
   //\r
-  // The Controller must support the Serial I/O Protocol.\r
-  // This driver is a bus driver with at most 1 child device, so it is\r
-  // ok for it to be already started.\r
+  // Open the EFI Device Path protocol needed to perform the supported test\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
-                  &gEfiSerialIoProtocolGuid,\r
-                  (VOID **) &SerialIo,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -191,12 +204,13 @@ TerminalDriverBindingSupported (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   //\r
-  // Close the I/O Abstraction(s) used to perform the supported test\r
+  // Close protocol, don't use device path protocol in the Support() function\r
   //\r
   gBS->CloseProtocol (\r
         Controller,\r
-        &gEfiSerialIoProtocolGuid,\r
+        &gEfiDevicePathProtocolGuid,\r
         This->DriverBindingHandle,\r
         Controller\r
         );\r
@@ -204,6 +218,186 @@ 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
+  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
+\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
+  }\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
+  Variable = GetEfiGlobalVariable (VariableName);\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
+\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
+\r
+**/\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  )\r
+{\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\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
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
 /**\r
   Start this driver on Controller by opening a Serial IO protocol,\r
   reading Device Path, and creating a child handle with a Simple Text In,\r
@@ -242,9 +436,22 @@ TerminalDriverBindingStart (
   UINTN                               Index;\r
   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL     *SimpleTextOutput;\r
-\r
-  TerminalDevice = NULL;\r
-  DefaultNode    = NULL;\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
+\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
   //\r
   // Get the Device Path Protocol to build the device path of the child device\r
   //\r
@@ -277,366 +484,543 @@ TerminalDriverBindingStart (
 \r
   if (Status != EFI_ALREADY_STARTED) {\r
     //\r
-    // If 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
+    // the serial I/O protocol never be opened before, it is the first\r
+    // time to start the serial Io controller\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
+    FirstEnter = TRUE;\r
   }\r
+\r
   //\r
-  // Make sure a child handle does not already exist.  This driver can only\r
-  // produce one child per serial port.\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->OpenProtocolInformation (\r
+  Status = gBS->OpenProtocol (\r
                   Controller,\r
-                  &gEfiSerialIoProtocolGuid,\r
-                  &OpenInfoBuffer,\r
-                  &EntryCount\r
+                  &gEfiCallerIdGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\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
+  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
-    FreePool (OpenInfoBuffer);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\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
-  // If RemainingDevicePath is NULL, then create default device path node\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
-    DefaultNode = AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH));\r
-    if (DefaultNode == 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
+    //\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, 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
-    TerminalType = FixedPcdGet8 (PcdDefaultTerminalType);\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->SimpleInputEx,\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->SimpleInput,\r
+                    &TerminalDevice->SimpleInput.WaitForKey\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
     //\r
-    // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)\r
+    // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
+    // the pre-read pending characters.\r
     //\r
-    ASSERT (TerminalType <= VTUTF8TYPE);\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
-    CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
-    RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DefaultNode;\r
-  } else {\r
     //\r
-    // Use the RemainingDevicePath to determine the terminal type\r
+    // Set the timeout value of serial buffer for\r
+    // keystroke response performance issue\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
+    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
-      goto Error;\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
+    TerminalDevice->SimpleTextOutputMode.MaxMode = 3;\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
-  //\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
+    Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReportError;\r
+    }\r
 \r
-  TerminalDevice->TerminalType  = TerminalType;\r
-  TerminalDevice->SerialIo      = SerialIo;\r
+    Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReportError;\r
+    }\r
 \r
-  InitializeListHead (&TerminalDevice->NotifyList);\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_WAIT,\r
-                  TPL_NOTIFY,\r
-                  TerminalConInWaitForKeyEx,\r
-                  &TerminalDevice->SimpleInputEx,\r
-                  &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto Error;\r
-  }\r
+    Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReportError;\r
+    }\r
 \r
+    Status = gBS->CreateEvent (\r
+                    EVT_TIMER,\r
+                    TPL_CALLBACK,\r
+                    NULL,\r
+                    NULL,\r
+                    &TerminalDevice->TwoSecondTimeOut\r
+                    );\r
 \r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_WAIT,\r
-                  TPL_NOTIFY,\r
-                  TerminalConInWaitForKey,\r
-                  &TerminalDevice->SimpleInput,\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
+    // 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
-  //\r
-  // Set the timeout value of serial buffer for\r
-  // keystroke response performance issue\r
-  //\r
-  Mode            = TerminalDevice->SerialIo->Mode;\r
+      break;\r
 \r
-  SerialInTimeOut = 0;\r
-  if (Mode->BaudRate != 0) {\r
-    SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\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
 \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
+    // Build the device path for the child device\r
     //\r
-    TerminalDevice->SerialInTimeOut = 0;\r
-  } else {\r
-    TerminalDevice->SerialInTimeOut = SerialInTimeOut;\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
+    Status = SetTerminalDevicePath (\r
+              TerminalDevice->TerminalType,\r
+              ParentDevicePath,\r
+              &TerminalDevice->DevicePath\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
 \r
-  DevicePath = TerminalDevice->DevicePath;\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
 \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
+    // Register the Parent-Child relationship via\r
+    // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
     //\r
-    goto ReportError;\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
-  //\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
-  TerminalDevice->SimpleTextOutputMode.MaxMode        = 3;\r
   //\r
-  // For terminal devices, cursor is always visible\r
+  // Find the child handle, and get its TerminalDevice private data\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
+  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 = TerminalConOutReset (SimpleTextOutput, FALSE);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ReportError;\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
 \r
-  Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
-  if (EFI_ERROR (Status)) {\r
+    FreePool (OpenInfoBuffer);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReportError;\r
+    }\r
+  } else {\r
     goto ReportError;\r
   }\r
 \r
-  Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ReportError;\r
+  ASSERT (TerminalDevice != NULL);\r
+  //\r
+  // Only do the reset if the device path is in the Conout variable\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
   }\r
 \r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER,\r
-                  TPL_CALLBACK,\r
-                  NULL,\r
-                  NULL,\r
-                  &TerminalDevice->TwoSecondTimeOut\r
-                  );\r
-\r
   //\r
-  // Build the component name for the child device\r
+  // Only output the configure string to remote terminal if the device path\r
+  // is in the Conout variable\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
+  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
-    break;\r
+    Status = TerminalDevice->SimpleTextOutput.Reset (\r
+                                                &TerminalDevice->SimpleTextOutput,\r
+                                                FALSE\r
+                                                );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReportError;\r
+    }\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
+    Status = TerminalDevice->SimpleTextOutput.SetMode (\r
+                                                &TerminalDevice->SimpleTextOutput,\r
+                                                0\r
+                                                );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReportError;\r
+    }\r
 \r
-    break;\r
-  }\r
-  //\r
-  // Install protocol interfaces for the serial device.\r
-  //\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &TerminalDevice->Handle,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  TerminalDevice->DevicePath,\r
-                  &gEfiSimpleTextInProtocolGuid,\r
-                  &TerminalDevice->SimpleInput,\r
-                  &gEfiSimpleTextInputExProtocolGuid,\r
-                  &TerminalDevice->SimpleInputEx,\r
-                  &gEfiSimpleTextOutProtocolGuid,\r
-                  &TerminalDevice->SimpleTextOutput,\r
-                  NULL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto Error;\r
+    Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
+                                                &TerminalDevice->SimpleTextOutput,\r
+                                                TRUE\r
+                                                );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReportError;\r
+    }\r
   }\r
 \r
   //\r
-  // Register the Parent-Child relationship via\r
-  // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\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
-  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
+  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
   }\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
+  }\r
   if (DefaultNode != NULL) {\r
     FreePool (DefaultNode);\r
   }\r
@@ -647,9 +1031,10 @@ ReportError:
   //\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
-    PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
+    (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\r
     DevicePath\r
     );\r
 \r
@@ -881,41 +1266,6 @@ TerminalDriverBindingStop (
   return EFI_SUCCESS;\r
 }\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
-\r
-**/\r
-EFI_STATUS\r
-TerminalFreeNotifyList (\r
-  IN OUT LIST_ENTRY           *ListHead\r
-  )\r
-{\r
-  TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\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
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
 /**\r
   Update terminal device path in Console Device Environment Variables.\r
 \r
@@ -936,16 +1286,14 @@ TerminalUpdateConsoleDevVariable (
   EFI_DEVICE_PATH_PROTOCOL  *NewVariable;\r
   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
 \r
-  Variable = NULL;\r
-\r
   //\r
   // Get global variable and its size according to the name given.\r
   //\r
-  Variable = TerminalGetVariableAndSize (\r
-              VariableName,\r
-              &gEfiGlobalVariableGuid,\r
-              &VariableSize\r
-              );\r
+  Variable = GetEfiGlobalVariable (VariableName);\r
+  if (Variable == NULL) {\r
+    return;\r
+  }\r
+\r
   //\r
   // Append terminal device path onto the variable.\r
   //\r
@@ -1005,17 +1353,12 @@ TerminalRemoveConsoleDevVariable (
   EFI_DEVICE_PATH_PROTOCOL  *SavedNewVariable;\r
   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
 \r
-  Variable  = NULL;\r
   Instance  = NULL;\r
 \r
   //\r
   // Get global variable and its size according to the name given.\r
   //\r
-  Variable = TerminalGetVariableAndSize (\r
-              VariableName,\r
-              &gEfiGlobalVariableGuid,\r
-              &VariableSize\r
-              );\r
+  Variable = GetEfiGlobalVariable (VariableName);\r
   if (Variable == NULL) {\r
     return ;\r
   }\r
@@ -1095,81 +1438,6 @@ TerminalRemoveConsoleDevVariable (
   return ;\r
 }\r
 \r
-\r
-/**\r
-  Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
-  buffer, and the size of the buffer. On failure return NULL.\r
-\r
-  @param  Name                   String part of EFI variable name\r
-  @param  VendorGuid             GUID part of EFI variable name\r
-  @param  VariableSize           Returns the size of the EFI variable that was read\r
-\r
-  @return Dynamically allocated memory that contains a copy of the EFI variable.\r
-          Caller is responsible freeing the buffer. If variable was not read,\r
-          NULL returned.\r
-\r
-**/\r
-VOID *\r
-TerminalGetVariableAndSize (\r
-  IN  CHAR16              *Name,\r
-  IN  EFI_GUID            *VendorGuid,\r
-  OUT UINTN               *VariableSize\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINTN       BufferSize;\r
-  VOID        *Buffer;\r
-\r
-  Buffer = NULL;\r
-\r
-  //\r
-  // Pass in a small size buffer to find the actual variable size.\r
-  //\r
-  BufferSize  = 1;\r
-  Buffer      = AllocatePool (BufferSize);\r
-  if (Buffer == NULL) {\r
-    *VariableSize = 0;\r
-    return NULL;\r
-  }\r
-\r
-  Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
-\r
-  if (Status == EFI_SUCCESS) {\r
-    *VariableSize = BufferSize;\r
-    return Buffer;\r
-\r
-  } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    //\r
-    // Allocate the buffer to return\r
-    //\r
-    FreePool (Buffer);\r
-    Buffer = AllocatePool (BufferSize);\r
-    if (Buffer == NULL) {\r
-      *VariableSize = 0;\r
-      return NULL;\r
-    }\r
-    //\r
-    // Read variable into the allocated buffer.\r
-    //\r
-    Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
-    if (EFI_ERROR (Status)) {\r
-      BufferSize = 0;\r
-      FreePool (Buffer);\r
-      Buffer = NULL;\r
-    }\r
-  } else {\r
-    //\r
-    // Variable not found or other errors met.\r
-    //\r
-    BufferSize = 0;\r
-    FreePool (Buffer);\r
-    Buffer = NULL;\r
-  }\r
-\r
-  *VariableSize = BufferSize;\r
-  return Buffer;\r
-}\r
-\r
 /**\r
   Build terminal device path according to terminal type.\r
 \r
@@ -1301,7 +1569,7 @@ IsHotPlugDevice (
   while (!IsDevicePathEnd (CheckDevicePath)) {\r
     //\r
     // Check device whether is hot plug device or not throught Device Path\r
-    // \r
+    //\r
     if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
         (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
          DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
@@ -1318,7 +1586,7 @@ IsHotPlugDevice (
       //\r
       return TRUE;\r
     }\r
-  \r
+\r
     CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
   }\r
 \r