]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
MdeModulePkg/ConSplitterDxe: Optimize the ConSplitterTextOutSetMode
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitter.c
index 181a2348049cae6de8ae1d9a3095cd48b4e46acd..63c814ae1816755f3011fcb588037d3dddea1320 100644 (file)
   never removed. Such design ensures sytem function well during none console\r
   device situation.\r
 \r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "ConSplitter.h"\r
 \r
+//\r
+// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode.\r
+// default not connect\r
+//\r
+BOOLEAN  mConInIsConnect = FALSE;\r
+\r
 //\r
 // Text In Splitter Private Data template\r
 //\r
@@ -60,6 +61,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA  mConIn = {
     (LIST_ENTRY *) NULL,\r
     (LIST_ENTRY *) NULL\r
   },\r
+  (EFI_KEY_DATA *) NULL,\r
+  0,\r
+  0,\r
+  FALSE,\r
 \r
   {\r
     ConSplitterSimplePointerReset,\r
@@ -169,14 +174,14 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
   (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
   0,\r
   0,\r
-  TRUE,\r
 \r
   0,\r
   (TEXT_OUT_AND_GOP_DATA *) NULL,\r
   0,\r
   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
   0,\r
-  (INT32 *) NULL\r
+  (INT32 *) NULL,\r
+  FALSE\r
 };\r
 \r
 //\r
@@ -225,14 +230,14 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
   (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
   0,\r
   0,\r
-  TRUE,\r
 \r
   0,\r
   (TEXT_OUT_AND_GOP_DATA *) NULL,\r
   0,\r
   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
   0,\r
-  (INT32 *) NULL\r
+  (INT32 *) NULL,\r
+  FALSE\r
 };\r
 \r
 //\r
@@ -295,6 +300,122 @@ EFI_DRIVER_BINDING_PROTOCOL           gConSplitterAbsolutePointerDriverBinding =
   NULL\r
 };\r
 \r
+/**\r
+  Key notify for toggle state sync.\r
+\r
+  @param KeyData        A pointer to a buffer that is filled in with\r
+                        the keystroke information for the key that was\r
+                        pressed.\r
+\r
+  @retval EFI_SUCCESS   Toggle state sync successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ToggleStateSyncKeyNotify (\r
+  IN EFI_KEY_DATA   *KeyData\r
+  )\r
+{\r
+  UINTN     Index;\r
+\r
+  if (((KeyData->KeyState.KeyToggleState & KEY_STATE_VALID_EXPOSED) == KEY_STATE_VALID_EXPOSED) &&\r
+      (KeyData->KeyState.KeyToggleState != mConIn.PhysicalKeyToggleState)) {\r
+    //\r
+    // There is toggle state change, sync to other console input devices.\r
+    //\r
+    for (Index = 0; Index < mConIn.CurrentNumberOfExConsoles; Index++) {\r
+      mConIn.TextInExList[Index]->SetState (\r
+                                    mConIn.TextInExList[Index],\r
+                                    &KeyData->KeyState.KeyToggleState\r
+                                    );\r
+    }\r
+    mConIn.PhysicalKeyToggleState = KeyData->KeyState.KeyToggleState;\r
+    DEBUG ((EFI_D_INFO, "Current toggle state is 0x%02x\n", mConIn.PhysicalKeyToggleState));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialization for toggle state sync.\r
+\r
+  @param Private                    Text In Splitter pointer.\r
+\r
+**/\r
+VOID\r
+ToggleStateSyncInitialization (\r
+  IN TEXT_IN_SPLITTER_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  EFI_KEY_DATA      KeyData;\r
+  VOID              *NotifyHandle;\r
+\r
+  //\r
+  // Initialize PhysicalKeyToggleState that will be synced to new console\r
+  // input device to turn on physical TextInEx partial key report for\r
+  // toggle state sync.\r
+  //\r
+  Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;\r
+\r
+  //\r
+  // Initialize VirtualKeyStateExported to let the virtual TextInEx not report\r
+  // the partial key even though the physical TextInEx turns on the partial\r
+  // key report. The virtual TextInEx will report the partial key after it is\r
+  // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.\r
+  //\r
+  Private->VirtualKeyStateExported = FALSE;\r
+\r
+  //\r
+  // Register key notify for toggle state sync.\r
+  //\r
+  KeyData.Key.ScanCode = SCAN_NULL;\r
+  KeyData.Key.UnicodeChar = CHAR_NULL;\r
+  KeyData.KeyState.KeyShiftState = 0;\r
+  KeyData.KeyState.KeyToggleState = 0;\r
+  Private->TextInEx.RegisterKeyNotify (\r
+                      &Private->TextInEx,\r
+                      &KeyData,\r
+                      ToggleStateSyncKeyNotify,\r
+                      &NotifyHandle\r
+                      );\r
+}\r
+\r
+/**\r
+  Reinitialization for toggle state sync.\r
+\r
+  @param Private                    Text In Splitter pointer.\r
+\r
+**/\r
+VOID\r
+ToggleStateSyncReInitialization (\r
+  IN TEXT_IN_SPLITTER_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  UINTN             Index;\r
+\r
+  //\r
+  // Reinitialize PhysicalKeyToggleState that will be synced to new console\r
+  // input device to turn on physical TextInEx partial key report for\r
+  // toggle state sync.\r
+  //\r
+  Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;\r
+\r
+  //\r
+  // Reinitialize VirtualKeyStateExported to let the virtual TextInEx not report\r
+  // the partial key even though the physical TextInEx turns on the partial\r
+  // key report. The virtual TextInEx will report the partial key after it is\r
+  // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.\r
+  //\r
+  Private->VirtualKeyStateExported = FALSE;\r
+\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Private->TextInExList[Index]->SetState (\r
+                                    Private->TextInExList[Index],\r
+                                    &Private->PhysicalKeyToggleState\r
+                                    );\r
+  }\r
+}\r
+\r
 /**\r
   The Entry Point for module ConSplitter. The user code starts with this function.\r
 \r
@@ -379,7 +500,7 @@ ConSplitterDriverEntry(
           FeaturePcdGet (PcdConOutUgaSupport));\r
 \r
   //\r
-  // The driver creates virtual handles for ConIn, ConOut.\r
+  // The driver creates virtual handles for ConIn, ConOut, StdErr.\r
   // The virtual handles will always exist even if no console exist in the\r
   // system. This is need to support hotplug devices like USB.\r
   //\r
@@ -414,49 +535,12 @@ ConSplitterDriverEntry(
   //\r
   Status = ConSplitterTextOutConstructor (&mConOut);\r
   if (!EFI_ERROR (Status)) {\r
-    if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
-      //\r
-      // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed\r
-      // on the virtual handle.\r
-      //\r
-      Status = gBS->InstallMultipleProtocolInterfaces (\r
-                      &mConOut.VirtualHandle,\r
-                      &gEfiSimpleTextOutProtocolGuid,\r
-                      &mConOut.TextOut,\r
-                      &gEfiUgaDrawProtocolGuid,\r
-                      &mConOut.UgaDraw,\r
-                      NULL\r
-                      );\r
-    } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
-      //\r
-      // If UGA Draw protocol not supported, Graphics Output Protocol is installed\r
-      // on virtual handle.\r
-      //\r
-      Status = gBS->InstallMultipleProtocolInterfaces (\r
-                      &mConOut.VirtualHandle,\r
-                      &gEfiSimpleTextOutProtocolGuid,\r
-                      &mConOut.TextOut,\r
-                      &gEfiGraphicsOutputProtocolGuid,\r
-                      &mConOut.GraphicsOutput,\r
-                      NULL\r
-                      );\r
-    } else {\r
-      //\r
-      // Boot Graphics Output protocol and UGA Draw protocol are supported,\r
-      // both they will be installed on virtual handle.\r
-      //\r
-      Status = gBS->InstallMultipleProtocolInterfaces (\r
-                      &mConOut.VirtualHandle,\r
-                      &gEfiSimpleTextOutProtocolGuid,\r
-                      &mConOut.TextOut,\r
-                      &gEfiGraphicsOutputProtocolGuid,\r
-                      &mConOut.GraphicsOutput,\r
-                      &gEfiUgaDrawProtocolGuid,\r
-                      &mConOut.UgaDraw,\r
-                      NULL\r
-                      );\r
-    }\r
-\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &mConOut.VirtualHandle,\r
+                    &gEfiSimpleTextOutProtocolGuid,\r
+                    &mConOut.TextOut,\r
+                    NULL\r
+                    );\r
     if (!EFI_ERROR (Status)) {\r
       //\r
       // Update the EFI System Table with new virtual console\r
@@ -467,6 +551,28 @@ ConSplitterDriverEntry(
     }\r
 \r
   }\r
+\r
+  //\r
+  // Create virtual device handle for StdErr Splitter\r
+  //\r
+  Status = ConSplitterTextOutConstructor (&mStdErr);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &mStdErr.VirtualHandle,\r
+                    &gEfiSimpleTextOutProtocolGuid,\r
+                    &mStdErr.TextOut,\r
+                    NULL\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Update the EFI System Table with new virtual console\r
+      // and update the pointer to Text Output protocol.\r
+      //\r
+      gST->StandardErrorHandle  = mStdErr.VirtualHandle;\r
+      gST->StdErr               = &mStdErr.TextOut;\r
+    }\r
+  }\r
+\r
   //\r
   // Update the CRC32 in the EFI System Table header\r
   //\r
@@ -498,6 +604,7 @@ ConSplitterTextInConstructor (
   )\r
 {\r
   EFI_STATUS  Status;\r
+  UINTN       TextInExListCount;\r
 \r
   //\r
   // Allocate buffer for Simple Text Input device\r
@@ -523,6 +630,19 @@ ConSplitterTextInConstructor (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // Allocate buffer for KeyQueue\r
+  //\r
+  TextInExListCount = ConInPrivate->TextInExListCount;\r
+  Status = ConSplitterGrowBuffer (\r
+             sizeof (EFI_KEY_DATA),\r
+             &TextInExListCount,\r
+             (VOID **) &ConInPrivate->KeyQueue\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
   //\r
   // Allocate buffer for Simple Text Input Ex device\r
   //\r
@@ -548,6 +668,8 @@ ConSplitterTextInConstructor (
 \r
   InitializeListHead (&ConInPrivate->NotifyList);\r
 \r
+  ToggleStateSyncInitialization (ConInPrivate);\r
+\r
   ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;\r
   //\r
   // Allocate buffer for Absolute Pointer device\r
@@ -594,6 +716,18 @@ ConSplitterTextInConstructor (
                   ConInPrivate,\r
                   &ConInPrivate->SimplePointer.WaitForInput\r
                   );\r
+  ASSERT_EFI_ERROR (Status);\r
+  //\r
+  // Create Event to signal ConIn connection request\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  EfiEventEmptyFunction,\r
+                  NULL,\r
+                  &gConnectConInEventGuid,\r
+                  &ConInPrivate->ConnectConInEvent\r
+                  );\r
 \r
   return Status;\r
 }\r
@@ -1277,7 +1411,7 @@ ConSplitterConOutDriverBindingStart (
 \r
       FreePool (Info);\r
 \r
-    } else if (UgaDraw != NULL  && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+    } else if (UgaDraw != NULL) {\r
       Status = UgaDraw->GetMode (\r
                  UgaDraw,\r
                  &mConOut.UgaHorizontalResolution,\r
@@ -1315,27 +1449,6 @@ ConSplitterStdErrDriverBindingStart (
   EFI_STATUS                       Status;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
 \r
-  if (mStdErr.CurrentNumberOfConsoles == 0) {\r
-    //\r
-    // Construct console output devices' private data\r
-    //\r
-    Status = ConSplitterTextOutConstructor (&mStdErr);\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Create virtual device handle for StdErr Splitter\r
-      //\r
-      Status = gBS->InstallMultipleProtocolInterfaces (\r
-                      &mStdErr.VirtualHandle,\r
-                      &gEfiSimpleTextOutProtocolGuid,\r
-                      &mStdErr.TextOut,\r
-                      NULL\r
-                      );\r
-    }\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-\r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
   // agrogated console device on first call Start for a StandardError handle.\r
@@ -1364,23 +1477,6 @@ ConSplitterStdErrDriverBindingStart (
   //\r
   Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);\r
   ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (mStdErr.CurrentNumberOfConsoles == 1) {\r
-    gST->StandardErrorHandle  = mStdErr.VirtualHandle;\r
-    gST->StdErr               = &mStdErr.TextOut;\r
-    //\r
-    // Update the CRC32 in the EFI System Table header\r
-    //\r
-    gST->Hdr.CRC32 = 0;\r
-    gBS->CalculateCrc32 (\r
-          (UINT8 *) &gST->Hdr,\r
-          gST->Hdr.HeaderSize,\r
-          &gST->Hdr.CRC32\r
-          );\r
-  }\r
 \r
   return Status;\r
 }\r
@@ -1718,48 +1814,17 @@ ConSplitterStdErrDriverBindingStop (
   //\r
   // Delete this console error out device's data structures.\r
   //\r
-  Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (mStdErr.CurrentNumberOfConsoles == 0) {\r
-    mStdErr.VirtualHandle     = NULL;\r
-\r
-    gST->StandardErrorHandle  = NULL;\r
-    gST->StdErr               = NULL;\r
-    //\r
-    // Update the CRC32 in the EFI System Table header\r
-    //\r
-    gST->Hdr.CRC32 = 0;\r
-    gBS->CalculateCrc32 (\r
-          (UINT8 *) &gST->Hdr,\r
-          gST->Hdr.HeaderSize,\r
-          &gST->Hdr.CRC32\r
-          );\r
-\r
-    //\r
-    // Uninstall Simple Text Output protocol from StdErr Handle.\r
-    //\r
-    gBS->UninstallMultipleProtocolInterfaces (\r
-           mStdErr.VirtualHandle,\r
-           &gEfiSimpleTextOutProtocolGuid,\r
-           &mStdErr.TextOut,\r
-           NULL\r
-           );\r
-  }\r
-\r
-  return Status;\r
+  return ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
 }\r
 \r
 \r
 /**\r
-  Take the passed in Buffer of size SizeOfCount and grow the buffer\r
-  by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount\r
-  bytes. Copy the current data in Buffer to the new version of Buffer\r
-  and free the old version of buffer.\r
+  Take the passed in Buffer of size ElementSize and grow the buffer\r
+  by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes.\r
+  Copy the current data in Buffer to the new version of Buffer and\r
+  free the old version of buffer.\r
 \r
-  @param  SizeOfCount              Size of element in array.\r
+  @param  ElementSize              Size of element in array.\r
   @param  Count                    Current number of elements in array.\r
   @param  Buffer                   Bigger version of passed in Buffer with all the\r
                                    data.\r
@@ -1770,7 +1835,7 @@ ConSplitterStdErrDriverBindingStop (
 **/\r
 EFI_STATUS\r
 ConSplitterGrowBuffer (\r
-  IN      UINTN                       SizeOfCount,\r
+  IN      UINTN                       ElementSize,\r
   IN OUT  UINTN                       *Count,\r
   IN OUT  VOID                        **Buffer\r
   )\r
@@ -1782,15 +1847,15 @@ ConSplitterGrowBuffer (
   // copy the old buffer's content to the new-size buffer,\r
   // then free the old buffer.\r
   //\r
-  *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;\r
   Ptr = ReallocatePool (\r
-          SizeOfCount * ((*Count) - CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT),\r
-          SizeOfCount * (*Count),\r
+          ElementSize * (*Count),\r
+          ElementSize * ((*Count) + CONSOLE_SPLITTER_ALLOC_UNIT),\r
           *Buffer\r
           );\r
   if (Ptr == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+  *Count += CONSOLE_SPLITTER_ALLOC_UNIT;\r
   *Buffer = Ptr;\r
   return EFI_SUCCESS;\r
 }\r
@@ -1865,7 +1930,7 @@ ConSplitterTextInDeleteDevice (
   //\r
   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
     if (Private->TextInList[Index] == TextIn) {\r
-      for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
+      for (; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
         Private->TextInList[Index] = Private->TextInList[Index + 1];\r
       }\r
 \r
@@ -1893,12 +1958,39 @@ ConSplitterTextInExAddDevice (
   IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_STATUS                  Status;\r
+  LIST_ENTRY                  *Link;\r
+  TEXT_IN_EX_SPLITTER_NOTIFY  *CurrentNotify;\r
+  UINTN                       TextInExListCount;\r
 \r
   //\r
-  // If the Text Input Ex List is full, enlarge it by calling ConSplitterGrowBuffer().\r
+  // Enlarge the NotifyHandleList and the TextInExList\r
   //\r
   if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
+    for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+      CurrentNotify     = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
+      TextInExListCount = Private->TextInExListCount;\r
+\r
+      Status = ConSplitterGrowBuffer (\r
+                 sizeof (EFI_HANDLE),\r
+                 &TextInExListCount,\r
+                 (VOID **) &CurrentNotify->NotifyHandleList\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+    }\r
+\r
+    TextInExListCount = Private->TextInExListCount;\r
+    Status = ConSplitterGrowBuffer (\r
+               sizeof (EFI_KEY_DATA),\r
+               &TextInExListCount,\r
+               (VOID **) &Private->KeyQueue\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
     Status = ConSplitterGrowBuffer (\r
               sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
               &Private->TextInExListCount,\r
@@ -1908,12 +2000,41 @@ ConSplitterTextInExAddDevice (
       return EFI_OUT_OF_RESOURCES;\r
     }\r
   }\r
+\r
+  //\r
+  // Register the key notify in the new text-in device\r
+  //\r
+  for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
+    Status = TextInEx->RegisterKeyNotify (\r
+                         TextInEx,\r
+                         &CurrentNotify->KeyData,\r
+                         CurrentNotify->KeyNotificationFn,\r
+                         &CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]\r
+                         );\r
+    if (EFI_ERROR (Status)) {\r
+      for (Link = Link->BackLink; Link != &Private->NotifyList; Link = Link->BackLink) {\r
+        CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
+        TextInEx->UnregisterKeyNotify (\r
+                    TextInEx,\r
+                    CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]\r
+                    );\r
+      }\r
+      return Status;\r
+    }\r
+  }\r
+\r
   //\r
   // Add the new text-in device data structure into the Text Input Ex List.\r
   //\r
   Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
   Private->CurrentNumberOfExConsoles++;\r
 \r
+  //\r
+  // Sync current toggle state to this new console input device.\r
+  //\r
+  TextInEx->SetState (TextInEx, &Private->PhysicalKeyToggleState);\r
+\r
   //\r
   // Extra CheckEvent added to reduce the double CheckEvent().\r
   //\r
@@ -1945,7 +2066,7 @@ ConSplitterTextInExDeleteDevice (
   //\r
   for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
     if (Private->TextInExList[Index] == TextInEx) {\r
-      for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
+      for (; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
         Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
       }\r
 \r
@@ -2022,7 +2143,7 @@ ConSplitterSimplePointerDeleteDevice (
   //\r
   for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
     if (Private->PointerList[Index] == SimplePointer) {\r
-      for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
+      for (; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
         Private->PointerList[Index] = Private->PointerList[Index + 1];\r
       }\r
 \r
@@ -2099,7 +2220,7 @@ ConSplitterAbsolutePointerDeleteDevice (
   //\r
   for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
     if (Private->AbsolutePointerList[Index] == AbsolutePointer) {\r
-      for (Index = Index; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
+      for (; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
         Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];\r
       }\r
 \r
@@ -2134,6 +2255,8 @@ ConSplitterGrowMapTable (
   INT32 *OldTextOutModeMap;\r
   INT32 *SrcAddress;\r
   INT32 Index;\r
+  UINTN OldStepSize;\r
+  UINTN NewStepSize;\r
 \r
   NewSize           = Private->TextOutListCount * sizeof (INT32);\r
   OldTextOutModeMap = Private->TextOutModeMap;\r
@@ -2171,14 +2294,26 @@ ConSplitterGrowMapTable (
     Size        = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
     Index       = 0;\r
     SrcAddress  = OldTextOutModeMap;\r
+    NewStepSize = NewSize / sizeof(INT32);\r
+    // If Private->CurrentNumberOfConsoles is not zero and OldTextOutModeMap\r
+    // is not NULL, it indicates that the original TextOutModeMap is not enough\r
+    // for the new console devices and has been enlarged by CONSOLE_SPLITTER_ALLOC_UNIT columns.\r
+    //\r
+    OldStepSize = NewStepSize - CONSOLE_SPLITTER_ALLOC_UNIT;\r
 \r
     //\r
     // Copy the old data to the new one\r
     //\r
     while (Index < Private->TextOutMode.MaxMode) {\r
       CopyMem (TextOutModeMap, SrcAddress, Size);\r
-      TextOutModeMap += NewSize;\r
-      SrcAddress += Size;\r
+      //\r
+      // Go to next row of new TextOutModeMap.\r
+      //\r
+      TextOutModeMap += NewStepSize;\r
+      //\r
+      // Go to next row of old TextOutModeMap.\r
+      //\r
+      SrcAddress += OldStepSize;\r
       Index++;\r
     }\r
     //\r
@@ -2526,7 +2661,7 @@ ConSplitterGetIntersectionBetweenConOutAndStrErr (
 \r
   //\r
   // Find the intersection of the two set of modes. If they actually intersect, the\r
-  // correponding entry in the map table is set to 1.\r
+  // corresponding entry in the map table is set to 1.\r
   //\r
   Mode = 0;\r
   while (Mode < ConOutMaxMode) {\r
@@ -2630,6 +2765,7 @@ ConSplitterAddGraphicsOutputMode (
 \r
   Index        = 0;\r
   CurrentIndex = 0;\r
+  Status       = EFI_SUCCESS;\r
 \r
   if (Private->CurrentNumberOfUgaDraw != 0) {\r
     //\r
@@ -2785,7 +2921,7 @@ ConSplitterAddGraphicsOutputMode (
         }\r
       }\r
     }\r
-  } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+  } else if (UgaDraw != NULL) {\r
     //\r
     // Graphics console driver can ensure the same mode for all GOP devices\r
     // so we can get the current mode from this video device\r
@@ -2825,30 +2961,55 @@ Done:
   if (GraphicsOutput != NULL) {\r
     Private->CurrentNumberOfGraphicsOutput++;\r
   }\r
-  if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+  if (UgaDraw != NULL) {\r
     Private->CurrentNumberOfUgaDraw++;\r
   }\r
 \r
   //\r
   // Force GraphicsOutput mode to be set,\r
-  // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
-  //\r
-  Private->HardwareNeedsStarting = TRUE;\r
   //\r
-  // Current mode number may need update now, so set it to an invalid mode number\r
-  //\r
-  CurrentGraphicsOutputMode->Mode = 0xffff;\r
-  //\r
-  // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.\r
-  //\r
-  Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex);\r
-  if (EFI_ERROR(Status)) {\r
+\r
+  Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];\r
+  if ((GraphicsOutput != NULL) &&\r
+      (Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&\r
+      (Mode->VerticalResolution == CurrentGraphicsOutputMode->Info->VerticalResolution)) {\r
+    CurrentGraphicsOutputMode->Mode = (UINT32) CurrentIndex;\r
+    if ((Mode->HorizontalResolution != GraphicsOutput->Mode->Info->HorizontalResolution) ||\r
+        (Mode->VerticalResolution != GraphicsOutput->Mode->Info->VerticalResolution)) {\r
+      //\r
+      // If all existing video device has been set to common mode, only set new GOP device to\r
+      // the common mode\r
+      //\r
+      for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {\r
+        Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+        if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {\r
+          FreePool (Info);\r
+          break;\r
+        }\r
+        FreePool (Info);\r
+      }\r
+      Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);\r
+    }\r
+  } else {\r
+    //\r
+    // Current mode number may need update now, so set it to an invalid mode number\r
     //\r
-    // If user defined mode is not valid for display device, set to the default mode 800x600.\r
+    CurrentGraphicsOutputMode->Mode = 0xffff;\r
     //\r
-    (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800;\r
-    (Private->GraphicsOutputModeBuffer[0]).VerticalResolution   = 600;\r
-    Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0);\r
+    // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.\r
+    //\r
+    Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex);\r
+    if (EFI_ERROR(Status)) {\r
+      //\r
+      // If user defined mode is not valid for display device, set to the default mode 800x600.\r
+      //\r
+      (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800;\r
+      (Private->GraphicsOutputModeBuffer[0]).VerticalResolution   = 600;\r
+      Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0);\r
+    }\r
   }\r
 \r
   return Status;\r
@@ -2877,6 +3038,7 @@ ConsplitterSetConsoleOutMode (
   UINTN                            MaxMode;\r
   EFI_STATUS                       Status;\r
   CONSOLE_OUT_MODE                 ModeInfo;\r
+  CONSOLE_OUT_MODE                 MaxModeInfo;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
 \r
   PreferMode   = 0xFF;\r
@@ -2884,8 +3046,10 @@ ConsplitterSetConsoleOutMode (
   TextOut      = &Private->TextOut;\r
   MaxMode      = (UINTN) (TextOut->Mode->MaxMode);\r
 \r
-  ModeInfo.Column = PcdGet32 (PcdConOutColumn);\r
-  ModeInfo.Row    = PcdGet32 (PcdConOutRow);\r
+  MaxModeInfo.Column = 0;\r
+  MaxModeInfo.Row    = 0;\r
+  ModeInfo.Column    = PcdGet32 (PcdConOutColumn);\r
+  ModeInfo.Row       = PcdGet32 (PcdConOutRow);\r
 \r
   //\r
   // To find the prefer mode and basic mode from Text Out mode list\r
@@ -2893,8 +3057,23 @@ ConsplitterSetConsoleOutMode (
   for (Mode = 0; Mode < MaxMode; Mode++) {\r
     Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);\r
     if (!EFI_ERROR(Status)) {\r
-      if (Col == ModeInfo.Column && Row == ModeInfo.Row) {\r
-        PreferMode = Mode;\r
+      if ((ModeInfo.Column != 0) && (ModeInfo.Row != 0)) {\r
+        //\r
+        // Use user defined column and row\r
+        //\r
+        if (Col == ModeInfo.Column && Row == ModeInfo.Row) {\r
+          PreferMode = Mode;\r
+        }\r
+      } else {\r
+        //\r
+        // If user sets PcdConOutColumn or PcdConOutRow to 0,\r
+        // find and set the highest text mode.\r
+        //\r
+        if ((Col >= MaxModeInfo.Column) && (Row >= MaxModeInfo.Row)) {\r
+          MaxModeInfo.Column  = Col;\r
+          MaxModeInfo.Row     = Row;\r
+          PreferMode          = Mode;\r
+        }\r
       }\r
       if (Col == 80 && Row == 25) {\r
         BaseMode = Mode;\r
@@ -2913,8 +3092,10 @@ ConsplitterSetConsoleOutMode (
     Status = TextOut->SetMode (TextOut, BaseMode);\r
     ASSERT(!EFI_ERROR(Status));\r
 \r
-    PcdSet32 (PcdConOutColumn, 80);\r
-    PcdSet32 (PcdConOutRow, 25);\r
+    Status = PcdSet32S (PcdConOutColumn, 80);\r
+    ASSERT(!EFI_ERROR(Status));\r
+    Status = PcdSet32S (PcdConOutRow, 25);\r
+    ASSERT(!EFI_ERROR(Status));\r
   }\r
 \r
   return ;\r
@@ -2953,8 +3134,9 @@ ConSplitterTextOutAddDevice (
   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
   EFI_STATUS                           DeviceStatus;\r
 \r
-  Status                = EFI_SUCCESS;\r
-  CurrentNumOfConsoles  = Private->CurrentNumberOfConsoles;\r
+  Status                      = EFI_SUCCESS;\r
+  CurrentNumOfConsoles        = Private->CurrentNumberOfConsoles;\r
+  Private->AddingConOutDevice = TRUE;\r
 \r
   //\r
   // If the Text Out List is full, enlarge it by calling ConSplitterGrowBuffer().\r
@@ -3005,18 +3187,16 @@ ConSplitterTextOutAddDevice (
   ASSERT (MaxMode >= 1);\r
 \r
   DeviceStatus = EFI_DEVICE_ERROR;\r
-  if (FeaturePcdGet (PcdConOutGopSupport)) {\r
-    //\r
-    // If GOP is produced by Consplitter, this device display mode will be added into Graphics Ouput modes.\r
-    //\r
-    if ((GraphicsOutput != NULL) || (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport))) {\r
-      DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
-    }\r
+  Status       = EFI_DEVICE_ERROR;\r
+\r
+  //\r
+  // This device display mode will be added into Graphics Ouput modes.\r
+  //\r
+  if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
+    DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
   }\r
 \r
   if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
-\r
-    Status = EFI_DEVICE_ERROR;\r
     //\r
     // If UGA is produced by Consplitter\r
     //\r
@@ -3032,7 +3212,7 @@ ConSplitterTextOutAddDevice (
 \r
       FreePool (Info);\r
 \r
-    } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+    } else if (UgaDraw != NULL) {\r
       Status = UgaDraw->GetMode (\r
                     UgaDraw,\r
                     &UgaHorizontalResolution,\r
@@ -3067,10 +3247,45 @@ ConSplitterTextOutAddDevice (
     }\r
   }\r
 \r
-  //\r
-  // If ConOut, then set the mode to Mode #0 which us 80 x 25\r
-  //\r
-  Private->TextOut.SetMode (&Private->TextOut, 0);\r
+  if (((!EFI_ERROR (DeviceStatus)) || (!EFI_ERROR (Status))) &&\r
+      ((Private->CurrentNumberOfGraphicsOutput + Private->CurrentNumberOfUgaDraw) == 1)) {\r
+    if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
+      //\r
+      // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed\r
+      // on the virtual handle.\r
+      //\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &mConOut.VirtualHandle,\r
+                      &gEfiUgaDrawProtocolGuid,\r
+                      &mConOut.UgaDraw,\r
+                      NULL\r
+                      );\r
+    } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
+      //\r
+      // If UGA Draw protocol not supported, Graphics Output Protocol is installed\r
+      // on virtual handle.\r
+      //\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &mConOut.VirtualHandle,\r
+                      &gEfiGraphicsOutputProtocolGuid,\r
+                      &mConOut.GraphicsOutput,\r
+                      NULL\r
+                      );\r
+    } else {\r
+      //\r
+      // Boot Graphics Output protocol and UGA Draw protocol are supported,\r
+      // both they will be installed on virtual handle.\r
+      //\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &mConOut.VirtualHandle,\r
+                      &gEfiGraphicsOutputProtocolGuid,\r
+                      &mConOut.GraphicsOutput,\r
+                      &gEfiUgaDrawProtocolGuid,\r
+                      &mConOut.UgaDraw,\r
+                      NULL\r
+                      );\r
+    }\r
+  }\r
 \r
   //\r
   // After adding new console device, all existing console devices should be\r
@@ -3078,6 +3293,8 @@ ConSplitterTextOutAddDevice (
   //\r
   ConsplitterSetConsoleOutMode (Private);\r
 \r
+  Private->AddingConOutDevice = FALSE;\r
+\r
   return Status;\r
 }\r
 \r
@@ -3112,14 +3329,14 @@ ConSplitterTextOutDeleteDevice (
   TextOutList           = Private->TextOutList;\r
   while (Index >= 0) {\r
     if (TextOutList->TextOut == TextOut) {\r
-      CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
-      CurrentNumOfConsoles--;\r
-      if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+      if (TextOutList->UgaDraw != NULL) {\r
         Private->CurrentNumberOfUgaDraw--;\r
       }\r
       if (TextOutList->GraphicsOutput != NULL) {\r
         Private->CurrentNumberOfGraphicsOutput--;\r
       }\r
+      CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
+      CurrentNumOfConsoles--;\r
       break;\r
     }\r
 \r
@@ -3133,6 +3350,35 @@ ConSplitterTextOutDeleteDevice (
     return EFI_NOT_FOUND;\r
   }\r
 \r
+  if ((Private->CurrentNumberOfGraphicsOutput == 0) && (Private->CurrentNumberOfUgaDraw == 0)) {\r
+    //\r
+    // If there is not any physical GOP and UGA device in system,\r
+    // Consplitter GOP or UGA protocol will be uninstalled\r
+    //\r
+    if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
+      Status = gBS->UninstallProtocolInterface (\r
+                      Private->VirtualHandle,\r
+                      &gEfiUgaDrawProtocolGuid,\r
+                      &Private->UgaDraw\r
+                      );\r
+    } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
+      Status = gBS->UninstallProtocolInterface (\r
+                      Private->VirtualHandle,\r
+                      &gEfiGraphicsOutputProtocolGuid,\r
+                      &Private->GraphicsOutput\r
+                      );\r
+    } else {\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+             Private->VirtualHandle,\r
+             &gEfiUgaDrawProtocolGuid,\r
+             &Private->UgaDraw,\r
+             &gEfiGraphicsOutputProtocolGuid,\r
+             &Private->GraphicsOutput,\r
+             NULL\r
+             );\r
+    }\r
+  }\r
+\r
   if (CurrentNumOfConsoles == 0) {\r
     //\r
     // If the number of consoles is zero, reset all parameters\r
@@ -3223,9 +3469,48 @@ ConSplitterTextInReset (
     }\r
   }\r
 \r
+  if (!EFI_ERROR (ReturnStatus)) {\r
+    ToggleStateSyncReInitialization (Private);\r
+    //\r
+    // Empty the key queue.\r
+    //\r
+    Private->CurrentNumberOfKeys = 0;\r
+  }\r
+\r
   return ReturnStatus;\r
 }\r
 \r
+/**\r
+  Dequeue the saved key from internal key queue.\r
+\r
+  @param  Private                  Protocol instance pointer.\r
+  @param  KeyData                  A pointer to a buffer that is filled in with the\r
+                                   keystroke state data for the key that was\r
+                                   pressed.\r
+  @retval EFI_NOT_FOUND            Queue is empty.\r
+  @retval EFI_SUCCESS              First key is dequeued and returned.\r
+**/\r
+EFI_STATUS\r
+ConSplitterTextInExDequeueKey (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
+  OUT EFI_KEY_DATA                    *KeyData\r
+  )\r
+{\r
+  if (Private->CurrentNumberOfKeys == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  //\r
+  // Return the first saved key.\r
+  //\r
+  CopyMem (KeyData, &Private->KeyQueue[0], sizeof (EFI_KEY_DATA));\r
+  Private->CurrentNumberOfKeys--;\r
+  CopyMem (\r
+    &Private->KeyQueue[0],\r
+    &Private->KeyQueue[1],\r
+    Private->CurrentNumberOfKeys * sizeof (EFI_KEY_DATA)\r
+    );\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Reads the next keystroke from the input device. The WaitForKey Event can\r
@@ -3249,7 +3534,21 @@ ConSplitterTextInPrivateReadKeyStroke (
 {\r
   EFI_STATUS    Status;\r
   UINTN         Index;\r
-  EFI_INPUT_KEY CurrentKey;\r
+  EFI_KEY_DATA  KeyData;\r
+\r
+  //\r
+  // Return the first saved non-NULL key.\r
+  //\r
+  while (TRUE) {\r
+    Status = ConSplitterTextInExDequeueKey (Private, &KeyData);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    if ((KeyData.Key.ScanCode != CHAR_NULL) || (KeyData.Key.UnicodeChar != SCAN_NULL)) {\r
+      CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+      return Status;\r
+    }\r
+  }\r
 \r
   Key->UnicodeChar  = 0;\r
   Key->ScanCode     = SCAN_NULL;\r
@@ -3259,14 +3558,25 @@ ConSplitterTextInPrivateReadKeyStroke (
   // if any physical console input device has key input,\r
   // return the key and EFI_SUCCESS.\r
   //\r
-  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
+  for (Index = 0; Index < Private->CurrentNumberOfConsoles;) {\r
     Status = Private->TextInList[Index]->ReadKeyStroke (\r
                                           Private->TextInList[Index],\r
-                                          &CurrentKey\r
+                                          &KeyData.Key\r
                                           );\r
     if (!EFI_ERROR (Status)) {\r
-      *Key = CurrentKey;\r
-      return Status;\r
+      //\r
+      // If it is not partial keystorke, return the key. Otherwise, continue\r
+      // to read key from THIS physical console input device.\r
+      //\r
+      if ((KeyData.Key.ScanCode != CHAR_NULL) || (KeyData.Key.UnicodeChar != SCAN_NULL)) {\r
+        CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+        return Status;\r
+      }\r
+    } else {\r
+      //\r
+      // Continue to read key from NEXT physical console input device.\r
+      //\r
+      Index++;\r
     }\r
   }\r
 \r
@@ -3274,6 +3584,7 @@ ConSplitterTextInPrivateReadKeyStroke (
 }\r
 \r
 \r
+\r
 /**\r
   Reads the next keystroke from the input device. The WaitForKey Event can\r
   be used to test for existance of a keystroke via WaitForEvent () call.\r
@@ -3300,6 +3611,15 @@ ConSplitterTextInReadKeyStroke (
 \r
   Private->KeyEventSignalState = FALSE;\r
 \r
+  //\r
+  // Signal ConnectConIn event on first call in Lazy ConIn mode\r
+  //\r
+  if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {\r
+    DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));\r
+    gBS->SignalEvent (Private->ConnectConInEvent);\r
+    mConInIsConnect = TRUE;\r
+  }\r
+\r
   return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
 }\r
 \r
@@ -3434,6 +3754,14 @@ ConSplitterTextInResetEx (
     }\r
   }\r
 \r
+  if (!EFI_ERROR (ReturnStatus)) {\r
+    ToggleStateSyncReInitialization (Private);\r
+    //\r
+    // Empty the key queue.\r
+    //\r
+    Private->CurrentNumberOfKeys = 0;\r
+  }\r
+\r
   return ReturnStatus;\r
 \r
 }\r
@@ -3465,6 +3793,7 @@ ConSplitterTextInReadKeyStrokeEx (
   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
   EFI_STATUS                    Status;\r
   UINTN                         Index;\r
+  EFI_KEY_STATE                 KeyState;\r
   EFI_KEY_DATA                  CurrentKeyData;\r
 \r
 \r
@@ -3476,25 +3805,91 @@ ConSplitterTextInReadKeyStrokeEx (
 \r
   Private->KeyEventSignalState = FALSE;\r
 \r
-  KeyData->Key.UnicodeChar  = 0;\r
-  KeyData->Key.ScanCode     = SCAN_NULL;\r
+  //\r
+  // Signal ConnectConIn event on first call in Lazy ConIn mode\r
+  //\r
+  if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {\r
+    DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));\r
+    gBS->SignalEvent (Private->ConnectConInEvent);\r
+    mConInIsConnect = TRUE;\r
+  }\r
 \r
   //\r
-  // if no physical console input device exists, return EFI_NOT_READY;\r
-  // if any physical console input device has key input,\r
-  // return the key and EFI_SUCCESS.\r
+  // Return the first saved key.\r
+  //\r
+  Status = ConSplitterTextInExDequeueKey (Private, KeyData);\r
+  if (!EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  ASSERT (Private->CurrentNumberOfKeys == 0);\r
+\r
+  ZeroMem (&KeyState, sizeof (KeyState));\r
+\r
+  //\r
+  // Iterate through all physical consoles to get key state.\r
+  // Some physical consoles may return valid key.\r
+  // Queue the valid keys.\r
   //\r
   for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    ZeroMem (&CurrentKeyData, sizeof (EFI_KEY_DATA));\r
     Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
-                                          Private->TextInExList[Index],\r
-                                          &CurrentKeyData\r
-                                          );\r
+                                             Private->TextInExList[Index],\r
+                                             &CurrentKeyData\r
+                                             );\r
+    if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Consolidate the key state from all physical consoles.\r
+    //\r
+    if ((CurrentKeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) {\r
+      KeyState.KeyShiftState |= CurrentKeyData.KeyState.KeyShiftState;\r
+    }\r
+    if ((CurrentKeyData.KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != 0) {\r
+      KeyState.KeyToggleState |= CurrentKeyData.KeyState.KeyToggleState;\r
+    }\r
+\r
     if (!EFI_ERROR (Status)) {\r
-      CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
-      return Status;\r
+      //\r
+      // If virtual KeyState has been required to be exposed, or it is not\r
+      // partial keystorke, queue the key.\r
+      // It's possible that user presses at multiple keyboards at the same moment,\r
+      // Private->KeyQueue[] are the storage to save all the keys.\r
+      //\r
+      if ((Private->VirtualKeyStateExported) ||\r
+          (CurrentKeyData.Key.ScanCode != CHAR_NULL) ||\r
+          (CurrentKeyData.Key.UnicodeChar != SCAN_NULL)) {\r
+        CopyMem (\r
+          &Private->KeyQueue[Private->CurrentNumberOfKeys],\r
+          &CurrentKeyData,\r
+          sizeof (EFI_KEY_DATA)\r
+          );\r
+        Private->CurrentNumberOfKeys++;\r
+      }\r
     }\r
   }\r
 \r
+  //\r
+  // Consolidate the key state for all keys in Private->KeyQueue[]\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfKeys; Index++) {\r
+    CopyMem (&Private->KeyQueue[Index].KeyState, &KeyState, sizeof (EFI_KEY_STATE));\r
+  }\r
+\r
+  //\r
+  // Return the first saved key.\r
+  //\r
+  Status = ConSplitterTextInExDequeueKey (Private, KeyData);\r
+  if (!EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Always return the key state even there is no key pressed.\r
+  //\r
+  ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
+  CopyMem (&KeyData->KeyState, &KeyState, sizeof (KeyData->KeyState));\r
   return EFI_NOT_READY;\r
 }\r
 \r
@@ -3524,6 +3919,7 @@ ConSplitterTextInSetState (
   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
   EFI_STATUS                    Status;\r
   UINTN                         Index;\r
+  EFI_KEY_TOGGLE_STATE          PhysicalKeyToggleState;\r
 \r
   if (KeyToggleState == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -3531,6 +3927,12 @@ ConSplitterTextInSetState (
 \r
   Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
+  //\r
+  // Always turn on physical TextInEx partial key report for\r
+  // toggle state sync.\r
+  //\r
+  PhysicalKeyToggleState = *KeyToggleState | EFI_KEY_STATE_EXPOSED;\r
+\r
   //\r
   // if no physical console input device exists, return EFI_SUCCESS;\r
   // otherwise return the status of setting state of physical console input device\r
@@ -3538,13 +3940,22 @@ ConSplitterTextInSetState (
   for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
     Status = Private->TextInExList[Index]->SetState (\r
                                              Private->TextInExList[Index],\r
-                                             KeyToggleState\r
+                                             &PhysicalKeyToggleState\r
                                              );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
   }\r
 \r
+  //\r
+  // Record the physical KeyToggleState.\r
+  //\r
+  Private->PhysicalKeyToggleState = PhysicalKeyToggleState;\r
+  //\r
+  // Get if virtual KeyState has been required to be exposed.\r
+  //\r
+  Private->VirtualKeyStateExported = (((*KeyToggleState) & EFI_KEY_STATE_EXPOSED) != 0);\r
+\r
   return EFI_SUCCESS;\r
 \r
 }\r
@@ -3554,11 +3965,14 @@ ConSplitterTextInSetState (
   Register a notification function for a particular keystroke for the input device.\r
 \r
   @param  This                     Protocol instance pointer.\r
-  @param  KeyData                  A pointer to a buffer that is filled in with the\r
-                                   keystroke information data for the key that was\r
-                                   pressed.\r
+  @param  KeyData                  A pointer to a buffer that is filled in with\r
+                                   the keystroke information for the key that was\r
+                                   pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState\r
+                                   and KeyData.KeyState.KeyShiftState are 0, then any incomplete\r
+                                   keystroke will trigger a notification of the KeyNotificationFunction.\r
   @param  KeyNotificationFunction  Points to the function to be called when the key\r
-                                   sequence is typed specified by KeyData.\r
+                                   sequence is typed specified by KeyData. This notification function\r
+                                   should be called at <=TPL_CALLBACK.\r
   @param  NotifyHandle             Points to the unique handle assigned to the\r
                                    registered notification.\r
 \r
@@ -3575,7 +3989,7 @@ ConSplitterTextInRegisterKeyNotify (
   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
   IN EFI_KEY_DATA                       *KeyData,\r
   IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,\r
-  OUT EFI_HANDLE                        *NotifyHandle\r
+  OUT VOID                              **NotifyHandle\r
   )\r
 {\r
   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
@@ -3592,14 +4006,6 @@ ConSplitterTextInRegisterKeyNotify (
 \r
   Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
-  //\r
-  // If no physical console input device exists,\r
-  // return EFI_SUCCESS directly.\r
-  //\r
-  if (Private->CurrentNumberOfExConsoles <= 0) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
   //\r
   // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
   //\r
@@ -3607,7 +4013,7 @@ ConSplitterTextInRegisterKeyNotify (
     CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
     if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
       if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
-        *NotifyHandle = CurrentNotify->NotifyHandle;\r
+        *NotifyHandle = CurrentNotify;\r
         return EFI_SUCCESS;\r
       }\r
     }\r
@@ -3620,15 +4026,14 @@ ConSplitterTextInRegisterKeyNotify (
   if (NewNotify == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
+  NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) *  Private->TextInExListCount);\r
   if (NewNotify->NotifyHandleList == NULL) {\r
     gBS->FreePool (NewNotify);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   NewNotify->Signature         = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;\r
   NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
-  NewNotify->NotifyHandle      = (EFI_HANDLE) NewNotify;\r
-  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
 \r
   //\r
   // Return the wrong status of registering key notify of\r
@@ -3642,15 +4047,24 @@ ConSplitterTextInRegisterKeyNotify (
                                              &NewNotify->NotifyHandleList[Index]\r
                                              );\r
     if (EFI_ERROR (Status)) {\r
+      //\r
+      // Un-register the key notify on all physical console input devices\r
+      //\r
+      while (Index-- != 0) {\r
+        Private->TextInExList[Index]->UnregisterKeyNotify (\r
+                                        Private->TextInExList[Index],\r
+                                        NewNotify->NotifyHandleList[Index]\r
+                                        );\r
+      }\r
       gBS->FreePool (NewNotify->NotifyHandleList);\r
       gBS->FreePool (NewNotify);\r
       return Status;\r
     }\r
   }\r
 \r
-  InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+  InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);\r
 \r
-  *NotifyHandle                = NewNotify->NotifyHandle;\r
+  *NotifyHandle                = NewNotify;\r
 \r
   return EFI_SUCCESS;\r
 \r
@@ -3673,11 +4087,10 @@ EFI_STATUS
 EFIAPI\r
 ConSplitterTextInUnregisterKeyNotify (\r
   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
-  IN EFI_HANDLE                         NotificationHandle\r
+  IN VOID                               *NotificationHandle\r
   )\r
 {\r
   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
-  EFI_STATUS                    Status;\r
   UINTN                         Index;\r
   TEXT_IN_EX_SPLITTER_NOTIFY    *CurrentNotify;\r
   LIST_ENTRY                    *Link;\r
@@ -3686,31 +4099,16 @@ ConSplitterTextInUnregisterKeyNotify (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (((TEXT_IN_EX_SPLITTER_NOTIFY *) NotificationHandle)->Signature != TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
-  //\r
-  // if no physical console input device exists,\r
-  // return EFI_SUCCESS directly.\r
-  //\r
-  if (Private->CurrentNumberOfExConsoles <= 0) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
   for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
     CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
-    if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+    if (CurrentNotify == NotificationHandle) {\r
       for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
-        Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
-                                                 Private->TextInExList[Index],\r
-                                                 CurrentNotify->NotifyHandleList[Index]\r
-                                                 );\r
-        if (EFI_ERROR (Status)) {\r
-          return Status;\r
-        }\r
+        Private->TextInExList[Index]->UnregisterKeyNotify (\r
+                                        Private->TextInExList[Index],\r
+                                        CurrentNotify->NotifyHandleList[Index]\r
+                                        );\r
       }\r
       RemoveEntryList (&CurrentNotify->NotifyEntry);\r
 \r
@@ -3996,7 +4394,18 @@ ConSplitterAbsolutePointerGetState (
   EFI_STATUS                    ReturnStatus;\r
   UINTN                         Index;\r
   EFI_ABSOLUTE_POINTER_STATE    CurrentState;\r
-\r
+  UINT64                        MinX;\r
+  UINT64                        MinY;\r
+  UINT64                        MinZ;\r
+  UINT64                        MaxX;\r
+  UINT64                        MaxY;\r
+  UINT64                        MaxZ;\r
+  UINT64                        VirtualMinX;\r
+  UINT64                        VirtualMinY;\r
+  UINT64                        VirtualMinZ;\r
+  UINT64                        VirtualMaxX;\r
+  UINT64                        VirtualMaxY;\r
+  UINT64                        VirtualMaxZ;\r
 \r
   Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
 \r
@@ -4007,6 +4416,13 @@ ConSplitterAbsolutePointerGetState (
   State->CurrentZ                        = 0;\r
   State->ActiveButtons                   = 0;\r
 \r
+  VirtualMinX = Private->AbsolutePointerMode.AbsoluteMinX;\r
+  VirtualMinY = Private->AbsolutePointerMode.AbsoluteMinY;\r
+  VirtualMinZ = Private->AbsolutePointerMode.AbsoluteMinZ;\r
+  VirtualMaxX = Private->AbsolutePointerMode.AbsoluteMaxX;\r
+  VirtualMaxY = Private->AbsolutePointerMode.AbsoluteMaxY;\r
+  VirtualMaxZ = Private->AbsolutePointerMode.AbsoluteMaxZ;\r
+\r
   //\r
   // if no physical pointer device exists, return EFI_NOT_READY;\r
   // if any physical pointer device has changed state,\r
@@ -4024,16 +4440,47 @@ ConSplitterAbsolutePointerGetState (
         ReturnStatus = EFI_SUCCESS;\r
       }\r
 \r
+      MinX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinX;\r
+      MinY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinY;\r
+      MinZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinZ;\r
+      MaxX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxX;\r
+      MaxY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxY;\r
+      MaxZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxZ;\r
+\r
       State->ActiveButtons = CurrentState.ActiveButtons;\r
 \r
-      if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {\r
-        State->CurrentX = CurrentState.CurrentX;\r
+      //\r
+      // Rescale to Con Splitter virtual Absolute Pointer's resolution.\r
+      //\r
+      if (!(MinX == 0 && MaxX == 0)) {\r
+        State->CurrentX = VirtualMinX + DivU64x64Remainder (\r
+                                          MultU64x64 (\r
+                                            CurrentState.CurrentX,\r
+                                            VirtualMaxX - VirtualMinX\r
+                                            ),\r
+                                          MaxX - MinX,\r
+                                          NULL\r
+                                          );\r
       }\r
-      if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {\r
-        State->CurrentY = CurrentState.CurrentY;\r
+      if (!(MinY == 0 && MaxY == 0)) {\r
+        State->CurrentY = VirtualMinY + DivU64x64Remainder (\r
+                                          MultU64x64 (\r
+                                            CurrentState.CurrentY,\r
+                                            VirtualMaxY - VirtualMinY\r
+                                            ),\r
+                                          MaxY - MinY,\r
+                                          NULL\r
+                                          );\r
       }\r
-      if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {\r
-        State->CurrentZ = CurrentState.CurrentZ;\r
+      if (!(MinZ == 0 && MaxZ == 0)) {\r
+        State->CurrentZ = VirtualMinZ + DivU64x64Remainder (\r
+                                          MultU64x64 (\r
+                                            CurrentState.CurrentZ,\r
+                                            VirtualMaxZ - VirtualMinZ\r
+                                            ),\r
+                                          MaxZ - MinZ,\r
+                                          NULL\r
+                                          );\r
       }\r
 \r
     } else if (Status == EFI_DEVICE_ERROR) {\r
@@ -4168,37 +4615,21 @@ ConSplitterTextOutOutputString (
   EFI_STATUS                      Status;\r
   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;\r
   UINTN                           Index;\r
-  UINTN                           BackSpaceCount;\r
   EFI_STATUS                      ReturnStatus;\r
-  CHAR16                          *TargetString;\r
+  UINTN                           MaxColumn;\r
+  UINTN                           MaxRow;\r
 \r
   This->SetAttribute (This, This->Mode->Attribute);\r
 \r
   Private         = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
-  BackSpaceCount  = 0;\r
-\r
-  for (TargetString = WString; *TargetString != L'\0'; TargetString++) {\r
-    if (*TargetString == CHAR_BACKSPACE) {\r
-      BackSpaceCount++;\r
-    }\r
-  }\r
-\r
-  if (BackSpaceCount == 0) {\r
-    TargetString = WString;\r
-  } else {\r
-    TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));\r
-    ASSERT (TargetString != NULL);\r
-\r
-    StrCpy (TargetString, WString);\r
-  }\r
   //\r
   // return the worst status met\r
   //\r
   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
     Status = Private->TextOutList[Index].TextOut->OutputString (\r
                                                     Private->TextOutList[Index].TextOut,\r
-                                                    TargetString\r
+                                                    WString\r
                                                     );\r
     if (EFI_ERROR (Status)) {\r
       ReturnStatus = Status;\r
@@ -4208,10 +4639,50 @@ ConSplitterTextOutOutputString (
   if (Private->CurrentNumberOfConsoles > 0) {\r
     Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn;\r
     Private->TextOutMode.CursorRow    = Private->TextOutList[0].TextOut->Mode->CursorRow;\r
-  }\r
+  } else {\r
+    //\r
+    // When there is no real console devices in system,\r
+    // update cursor position for the virtual device in consplitter.\r
+    //\r
+    Private->TextOut.QueryMode (\r
+                       &Private->TextOut,\r
+                       Private->TextOutMode.Mode,\r
+                       &MaxColumn,\r
+                       &MaxRow\r
+                       );\r
+    for (; *WString != CHAR_NULL; WString++) {\r
+      switch (*WString) {\r
+      case CHAR_BACKSPACE:\r
+        if (Private->TextOutMode.CursorColumn == 0 && Private->TextOutMode.CursorRow > 0) {\r
+          Private->TextOutMode.CursorRow--;\r
+          Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1);\r
+        } else if (Private->TextOutMode.CursorColumn > 0) {\r
+          Private->TextOutMode.CursorColumn--;\r
+        }\r
+        break;\r
+\r
+      case CHAR_LINEFEED:\r
+        if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
+          Private->TextOutMode.CursorRow++;\r
+        }\r
+        break;\r
+\r
+      case CHAR_CARRIAGE_RETURN:\r
+        Private->TextOutMode.CursorColumn = 0;\r
+        break;\r
 \r
-  if (BackSpaceCount > 0) {\r
-    FreePool (TargetString);\r
+      default:\r
+        if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {\r
+          Private->TextOutMode.CursorColumn++;\r
+        } else {\r
+          Private->TextOutMode.CursorColumn = 0;\r
+          if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
+            Private->TextOutMode.CursorRow++;\r
+          }\r
+        }\r
+        break;\r
+      }\r
+    }\r
   }\r
 \r
   return ReturnStatus;\r
@@ -4383,20 +4854,18 @@ ConSplitterTextOutSetMode (
   //\r
   TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
-    Status = Private->TextOutList[Index].TextOut->SetMode (\r
-                                                    Private->TextOutList[Index].TextOut,\r
-                                                    TextOutModeMap[Index]\r
-                                                    );\r
     //\r
-    // If this console device is based on a GOP or UGA device, then sync up the bitmap from\r
-    // the GOP/UGA splitter and reclear the text portion of the display in the new mode.\r
+    // While adding a console out device do not set same mode again for the same device.\r
     //\r
-    if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
-      Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
-    }\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      ReturnStatus = Status;\r
+    if ((!Private->AddingConOutDevice) ||\r
+        (TextOutModeMap[Index] != Private->TextOutList[Index].TextOut->Mode->Mode)) {\r
+      Status = Private->TextOutList[Index].TextOut->SetMode (\r
+                                                      Private->TextOutList[Index].TextOut,\r
+                                                      TextOutModeMap[Index]\r
+                                                      );\r
+      if (EFI_ERROR (Status)) {\r
+        ReturnStatus = Status;\r
+      }\r
     }\r
   }\r
 \r
@@ -4443,7 +4912,7 @@ ConSplitterTextOutSetAttribute (
   //\r
   // Check whether param Attribute is valid.\r
   //\r
-  if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {\r
+  if ((Attribute | 0x7F) != 0x7F) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -4642,4 +5111,3 @@ ConSplitterTextOutEnableCursor (
 \r
   return ReturnStatus;\r
 }\r
-\r