]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
MdeModulePkg/Graphics: Fix spelling mistakes
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitter.c
index 12deda7bb777098b785c02f6dd9c8892c079bda0..b090de288517780c52e1b9e2ebf492f17101a135 100644 (file)
@@ -1,5 +1,5 @@
 /** @file\r
-  Console Splitter Driver. Any Handle that attatched console I/O protocols\r
+  Console Splitter Driver. Any Handle that attached console I/O protocols\r
   (Console In device, Console Out device, Console Error device, Simple Pointer\r
   protocol, Absolute Pointer protocol) can be bound by this driver.\r
 \r
 \r
   Each virtual handle, that supports the Console I/O protocol, will be produced\r
   in the driver entry point. The virtual handle are added on driver entry and\r
-  never removed. Such design ensures sytem function well during none console\r
+  never removed. Such design ensures system 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
+  Re-initialization 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
@@ -488,7 +594,7 @@ ConSplitterDriverEntry(
                                    structure.\r
 \r
   @retval EFI_OUT_OF_RESOURCES     Out of resources.\r
-  @retval EFI_SUCCESS              Text Input Devcie's private data has been constructed.\r
+  @retval EFI_SUCCESS              Text Input Device's private data has been constructed.\r
   @retval other                    Failed to construct private data.\r
 \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
@@ -627,7 +761,7 @@ ConSplitterTextOutConstructor (
   }\r
 \r
   //\r
-  // Initilize console output splitter's private data.\r
+  // Initialize console output splitter's private data.\r
   //\r
   ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;\r
 \r
@@ -726,7 +860,7 @@ ConSplitterTextOutConstructor (
   @param  Guid                The specified protocol.\r
 \r
   @retval EFI_SUCCESS         The specified protocol is supported on this device.\r
-  @retval EFI_UNSUPPORTED     The specified protocol attempts to be installed on virtul handle.\r
+  @retval EFI_UNSUPPORTED     The specified protocol attempts to be installed on virtual handle.\r
   @retval other               Failed to open specified protocol on this device.\r
 \r
 **/\r
@@ -974,7 +1108,7 @@ ConSplitterStart (
   }\r
 \r
   //\r
-  // Open InterfaceGuid on the virtul handle.\r
+  // Open InterfaceGuid on the virtual handle.\r
   //\r
   Status =  gBS->OpenProtocol (\r
                 ControllerHandle,\r
@@ -1040,7 +1174,7 @@ ConSplitterConInDriverBindingStart (
 \r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
-  // agrogated console device on first call Start for a SimpleTextIn handle.\r
+  // aggregated console device on first call Start for a SimpleTextIn handle.\r
   //\r
   Status = ConSplitterStart (\r
             This,\r
@@ -1107,7 +1241,7 @@ ConSplitterSimplePointerDriverBindingStart (
 \r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
-  // agrogated console device on first call Start for a SimplePointer handle.\r
+  // aggregated console device on first call Start for a SimplePointer handle.\r
   //\r
   Status = ConSplitterStart (\r
             This,\r
@@ -1153,7 +1287,7 @@ ConSplitterAbsolutePointerDriverBindingStart (
 \r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
-  // agrogated console device on first call Start for a AbsolutePointer handle.\r
+  // aggregated console device on first call Start for a AbsolutePointer handle.\r
   //\r
   Status = ConSplitterStart (\r
              This,\r
@@ -1204,7 +1338,7 @@ ConSplitterConOutDriverBindingStart (
 \r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
-  // agrogated console device on first call Start for a ConsoleOut handle.\r
+  // aggregated console device on first call Start for a ConsoleOut handle.\r
   //\r
   Status = ConSplitterStart (\r
             This,\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,30 +1449,9 @@ 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
+  // aggregated console device on first call Start for a StandardError handle.\r
   //\r
   Status = ConSplitterStart (\r
             This,\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
@@ -1426,7 +1522,7 @@ ConSplitterStop (
     return Status;\r
   }\r
   //\r
-  // close the protocol refered.\r
+  // close the protocol referred.\r
   //\r
   gBS->CloseProtocol (\r
         ControllerHandle,\r
@@ -1447,7 +1543,7 @@ ConSplitterStop (
 \r
 \r
 /**\r
-  Stop Console In ConSplitter on ControllerHandle by closing Console In Devcice GUID.\r
+  Stop Console In ConSplitter on ControllerHandle by closing Console In Device GUID.\r
 \r
   @param  This              Driver Binding protocol instance pointer.\r
   @param  ControllerHandle  Handle of device to stop driver on\r
@@ -1622,7 +1718,7 @@ ConSplitterAbsolutePointerDriverBindingStop (
 \r
 \r
 /**\r
-  Stop Console Out ConSplitter on device handle by closing Console Out Devcice GUID.\r
+  Stop Console Out ConSplitter on device handle by closing Console Out Devcie GUID.\r
 \r
   @param  This              Driver Binding protocol instance pointer.\r
   @param  ControllerHandle  Handle of device to stop driver on\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
@@ -2590,7 +2725,7 @@ ConSplitterGetIntersectionBetweenConOutAndStrErr (
 \r
 \r
 /**\r
-  Add Grahpics Output modes into Consplitter Text Out list.\r
+  Add Graphics Output modes into Consplitter Text Out list.\r
 \r
   @param  Private               Text Out Splitter pointer.\r
   @param  GraphicsOutput        Graphics Output protocol pointer.\r
@@ -2786,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
@@ -2826,16 +2961,14 @@ 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
+\r
   Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];\r
   if ((GraphicsOutput != NULL) &&\r
       (Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&\r
@@ -2905,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
@@ -2912,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
@@ -2921,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
@@ -2941,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
@@ -2981,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
@@ -3033,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
@@ -3060,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
@@ -3095,12 +3247,54 @@ ConSplitterTextOutAddDevice (
     }\r
   }\r
 \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
   // synced to the current shared mode.\r
   //\r
   ConsplitterSetConsoleOutMode (Private);\r
 \r
+  Private->AddingConOutDevice = FALSE;\r
+\r
   return Status;\r
 }\r
 \r
@@ -3135,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
@@ -3156,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
@@ -3169,7 +3392,7 @@ ConSplitterTextOutDeleteDevice (
     return EFI_SUCCESS;\r
   }\r
   //\r
-  // Max Mode is realy an intersection of the QueryMode command to all\r
+  // Max Mode is really an intersection of the QueryMode command to all\r
   // devices. So we must copy the QueryMode of the first device to\r
   // QueryData.\r
   //\r
@@ -3207,7 +3430,7 @@ ConSplitterTextOutDeleteDevice (
 \r
 \r
 /**\r
-  Reset the input device and optionaly run diagnostics\r
+  Reset the input device and optionally run diagnostics\r
 \r
   @param  This                     Protocol instance pointer.\r
   @param  ExtendedVerification     Driver may perform diagnostics on reset.\r
@@ -3246,13 +3469,52 @@ 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
-  be used to test for existance of a keystroke via WaitForEvent () call.\r
+  be used to test for existence of a keystroke via WaitForEvent () call.\r
 \r
   @param  Private                  Protocol instance pointer.\r
   @param  Key                      Driver may perform diagnostics on reset.\r
@@ -3272,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
@@ -3282,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
@@ -3297,9 +3584,10 @@ 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
+  be used to test for existence of a keystroke via WaitForEvent () call.\r
 \r
   @param  This                     Protocol instance pointer.\r
   @param  Key                      Driver may perform diagnostics on reset.\r
@@ -3323,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
@@ -3334,7 +3631,7 @@ ConSplitterTextInReadKeyStroke (
   spliter event. This will cause the calling code to call\r
   ConSplitterTextInReadKeyStroke ().\r
 \r
-  @param  Event                    The Event assoicated with callback.\r
+  @param  Event                    The Event associated with callback.\r
   @param  Context                  Context registered when Event was created.\r
 \r
 **/\r
@@ -3384,7 +3681,7 @@ ConSplitterTextInWaitForKey (
                                    pressed.\r
 \r
   @retval TRUE                     Key be pressed matches a registered key.\r
-  @retval FLASE                    Match failed.\r
+  @retval FALSE                    Match failed.\r
 \r
 **/\r
 BOOLEAN\r
@@ -3418,7 +3715,7 @@ IsKeyRegistered (
 \r
 \r
 /**\r
-  Reset the input device and optionaly run diagnostics\r
+  Reset the input device and optionally run diagnostics\r
 \r
   @param  This                     Protocol instance pointer.\r
   @param  ExtendedVerification     Driver may perform diagnostics on reset.\r
@@ -3457,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
@@ -3464,7 +3769,7 @@ ConSplitterTextInResetEx (
 \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
+  be used to test for existence of a keystroke via WaitForEvent () call.\r
 \r
   @param  This                     Protocol instance pointer.\r
   @param  KeyData                  A pointer to a buffer that is filled in with the\r
@@ -3488,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
@@ -3499,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
@@ -3547,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
@@ -3554,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
@@ -3561,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
@@ -3577,17 +3965,20 @@ 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
   @retval EFI_SUCCESS              The notification function was registered\r
                                    successfully.\r
-  @retval EFI_OUT_OF_RESOURCES     Unable to allocate resources for necesssary data\r
+  @retval EFI_OUT_OF_RESOURCES     Unable to allocate resources for necessary data\r
                                    structures.\r
   @retval EFI_INVALID_PARAMETER    KeyData or KeyNotificationFunction or NotifyHandle is NULL.\r
 \r
@@ -3598,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
@@ -3615,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
@@ -3630,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
@@ -3643,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 = (VOID **) AllocateZeroPool (sizeof (VOID *) *  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
@@ -3665,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
@@ -3696,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
@@ -3709,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
@@ -3751,7 +4126,7 @@ ConSplitterTextInUnregisterKeyNotify (
 \r
 \r
 /**\r
-  Reset the input device and optionaly run diagnostics\r
+  Reset the input device and optionally run diagnostics\r
 \r
   @param  This                     Protocol instance pointer.\r
   @param  ExtendedVerification     Driver may perform diagnostics on reset.\r
@@ -3799,7 +4174,7 @@ ConSplitterSimplePointerReset (
 \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
+  be used to test for existence of a keystroke via WaitForEvent () call.\r
 \r
   @param  Private                  Protocol instance pointer.\r
   @param  State                    The state information of simple pointer device.\r
@@ -3904,12 +4279,12 @@ ConSplitterSimplePointerGetState (
 \r
 \r
 /**\r
-  This event agregates all the events of the ConIn devices in the spliter.\r
+  This event aggregates all the events of the ConIn devices in the spliter.\r
   If any events of physical ConIn devices are signaled, signal the ConIn\r
   spliter event. This will cause the calling code to call\r
   ConSplitterTextInReadKeyStroke ().\r
 \r
-  @param  Event                    The Event assoicated with callback.\r
+  @param  Event                    The Event associated with callback.\r
   @param  Context                  Context registered when Event was created.\r
 \r
 **/\r
@@ -4019,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
@@ -4030,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
@@ -4047,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
@@ -4069,12 +4493,12 @@ ConSplitterAbsolutePointerGetState (
 \r
 \r
 /**\r
-  This event agregates all the events of the pointer devices in the splitter.\r
+  This event aggregates all the events of the pointer devices in the splitter.\r
   If any events of physical pointer devices are signaled, signal the pointer\r
   splitter event. This will cause the calling code to call\r
   ConSplitterAbsolutePointerGetState ().\r
 \r
-  @param  Event                    The Event assoicated with callback.\r
+  @param  Event                    The Event associated with callback.\r
   @param  Context                  Context registered when Event was created.\r
 \r
 **/\r
@@ -4113,10 +4537,10 @@ ConSplitterAbsolutePointerWaitForInput (
 \r
 \r
 /**\r
-  Reset the text output device hardware and optionaly run diagnostics\r
+  Reset the text output device hardware and optionally run diagnostics\r
 \r
   @param  This                     Protocol instance pointer.\r
-  @param  ExtendedVerification     Driver may perform more exhaustive verfication\r
+  @param  ExtendedVerification     Driver may perform more exhaustive verification\r
                                    operation of the device during reset.\r
 \r
   @retval EFI_SUCCESS              The text output device was reset.\r
@@ -4191,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
@@ -4231,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
-  if (BackSpaceCount > 0) {\r
-    FreePool (TargetString);\r
+      case CHAR_CARRIAGE_RETURN:\r
+        Private->TextOutMode.CursorColumn = 0;\r
+        break;\r
+\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
@@ -4406,12 +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
-    if (EFI_ERROR (Status)) {\r
-      ReturnStatus = Status;\r
+    //\r
+    // While adding a console out device do not set same mode again for the same device.\r
+    //\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
@@ -4458,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
@@ -4657,4 +5111,3 @@ ConSplitterTextOutEnableCursor (
 \r
   return ReturnStatus;\r
 }\r
-\r