]> 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 a0a2dd3358954a07a40a5e658f6382cf6dd822b4..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 - 2012, 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
+// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode.\r
 // default not connect\r
 //\r
 BOOLEAN  mConInIsConnect = FALSE;\r
@@ -66,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
@@ -181,7 +180,8 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
   0,\r
   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
   0,\r
-  (INT32 *) NULL\r
+  (INT32 *) NULL,\r
+  FALSE\r
 };\r
 \r
 //\r
@@ -236,7 +236,8 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
   0,\r
   (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
   0,\r
-  (INT32 *) NULL\r
+  (INT32 *) NULL,\r
+  FALSE\r
 };\r
 \r
 //\r
@@ -299,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
@@ -446,7 +563,7 @@ ConSplitterDriverEntry(
                     &mStdErr.TextOut,\r
                     NULL\r
                     );\r
-    if (!EFI_ERROR (Status)) {  \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
@@ -455,7 +572,7 @@ ConSplitterDriverEntry(
       gST->StdErr               = &mStdErr.TextOut;\r
     }\r
   }\r
-  \r
+\r
   //\r
   // Update the CRC32 in the EFI System Table header\r
   //\r
@@ -477,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
@@ -487,6 +604,7 @@ ConSplitterTextInConstructor (
   )\r
 {\r
   EFI_STATUS  Status;\r
+  UINTN       TextInExListCount;\r
 \r
   //\r
   // Allocate buffer for Simple Text Input device\r
@@ -512,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
@@ -537,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
@@ -590,7 +723,7 @@ ConSplitterTextInConstructor (
   Status = gBS->CreateEventEx (\r
                   EVT_NOTIFY_SIGNAL,\r
                   TPL_CALLBACK,\r
-                  ConSplitterEmptyCallbackFunction,\r
+                  EfiEventEmptyFunction,\r
                   NULL,\r
                   &gConnectConInEventGuid,\r
                   &ConInPrivate->ConnectConInEvent\r
@@ -628,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
@@ -727,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
@@ -975,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
@@ -1041,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
@@ -1108,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
@@ -1154,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
@@ -1205,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
@@ -1318,7 +1451,7 @@ ConSplitterStdErrDriverBindingStart (
 \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
@@ -1344,9 +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
   return Status;\r
 }\r
@@ -1392,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
@@ -1413,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
@@ -1588,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
@@ -1850,6 +1980,17 @@ ConSplitterTextInExAddDevice (
         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
@@ -1889,6 +2030,11 @@ ConSplitterTextInExAddDevice (
   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
@@ -2148,7 +2294,7 @@ ConSplitterGrowMapTable (
     Size        = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
     Index       = 0;\r
     SrcAddress  = OldTextOutModeMap;\r
-    NewStepSize = NewSize / sizeof(INT32);    \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
@@ -2515,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
@@ -2579,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
@@ -2822,7 +2968,7 @@ Done:
   //\r
   // Force GraphicsOutput mode to be set,\r
   //\r
-  \r
+\r
   Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];\r
   if ((GraphicsOutput != NULL) &&\r
       (Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&\r
@@ -2901,7 +3047,7 @@ ConsplitterSetConsoleOutMode (
   MaxMode      = (UINTN) (TextOut->Mode->MaxMode);\r
 \r
   MaxModeInfo.Column = 0;\r
-  MaxModeInfo.Row    = 0; \r
+  MaxModeInfo.Row    = 0;\r
   ModeInfo.Column    = PcdGet32 (PcdConOutColumn);\r
   ModeInfo.Row       = PcdGet32 (PcdConOutRow);\r
 \r
@@ -2946,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
@@ -2986,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
@@ -3039,7 +3188,7 @@ ConSplitterTextOutAddDevice (
 \r
   DeviceStatus = EFI_DEVICE_ERROR;\r
   Status       = EFI_DEVICE_ERROR;\r
-  \r
+\r
   //\r
   // This device display mode will be added into Graphics Ouput modes.\r
   //\r
@@ -3144,6 +3293,8 @@ ConSplitterTextOutAddDevice (
   //\r
   ConsplitterSetConsoleOutMode (Private);\r
 \r
+  Private->AddingConOutDevice = FALSE;\r
+\r
   return Status;\r
 }\r
 \r
@@ -3209,7 +3360,7 @@ ConSplitterTextOutDeleteDevice (
                       Private->VirtualHandle,\r
                       &gEfiUgaDrawProtocolGuid,\r
                       &Private->UgaDraw\r
-                      );      \r
+                      );\r
     } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
       Status = gBS->UninstallProtocolInterface (\r
                       Private->VirtualHandle,\r
@@ -3241,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
@@ -3279,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
@@ -3318,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
@@ -3344,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
@@ -3354,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
@@ -3372,7 +3587,7 @@ ConSplitterTextInPrivateReadKeyStroke (
 \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
@@ -3400,7 +3615,7 @@ ConSplitterTextInReadKeyStroke (
   // 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
+    DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));\r
     gBS->SignalEvent (Private->ConnectConInEvent);\r
     mConInIsConnect = TRUE;\r
   }\r
@@ -3416,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
@@ -3466,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
@@ -3500,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
@@ -3539,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
@@ -3546,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
@@ -3570,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
@@ -3581,34 +3805,91 @@ ConSplitterTextInReadKeyStrokeEx (
 \r
   Private->KeyEventSignalState = FALSE;\r
 \r
-  KeyData->Key.UnicodeChar  = 0;\r
-  KeyData->Key.ScanCode     = SCAN_NULL;\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
+    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
@@ -3638,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
@@ -3645,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
@@ -3652,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
@@ -3668,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
@@ -3726,7 +4026,7 @@ ConSplitterTextInRegisterKeyNotify (
   if (NewNotify == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) *  Private->TextInExListCount);\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
@@ -3762,7 +4062,7 @@ ConSplitterTextInRegisterKeyNotify (
     }\r
   }\r
 \r
-  InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+  InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);\r
 \r
   *NotifyHandle                = NewNotify;\r
 \r
@@ -3826,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
@@ -3874,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
@@ -3979,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
@@ -4094,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
@@ -4105,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
@@ -4122,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
@@ -4144,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
@@ -4188,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
@@ -4292,7 +4641,7 @@ ConSplitterTextOutOutputString (
     Private->TextOutMode.CursorRow    = Private->TextOutList[0].TextOut->Mode->CursorRow;\r
   } else {\r
     //\r
-    // When there is no real console devices in system, \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
@@ -4300,28 +4649,28 @@ ConSplitterTextOutOutputString (
                        Private->TextOutMode.Mode,\r
                        &MaxColumn,\r
                        &MaxRow\r
-                       );    \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
+          Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1);\r
         } else if (Private->TextOutMode.CursorColumn > 0) {\r
           Private->TextOutMode.CursorColumn--;\r
         }\r
         break;\r
-      \r
+\r
       case CHAR_LINEFEED:\r
         if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
           Private->TextOutMode.CursorRow++;\r
         }\r
         break;\r
-      \r
+\r
       case CHAR_CARRIAGE_RETURN:\r
         Private->TextOutMode.CursorColumn = 0;\r
         break;\r
-      \r
+\r
       default:\r
         if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {\r
           Private->TextOutMode.CursorColumn++;\r
@@ -4505,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
@@ -4557,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
@@ -4756,21 +5111,3 @@ ConSplitterTextOutEnableCursor (
 \r
   return ReturnStatus;\r
 }\r
-\r
-\r
-/**\r
-  An empty function to pass error checking of CreateEventEx ().\r
-\r
-  @param  Event                 Event whose notification function is being invoked.\r
-  @param  Context               Pointer to the notification function's context,\r
-                                which is implementation-dependent.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ConSplitterEmptyCallbackFunction (\r
-  IN EFI_EVENT                Event,\r
-  IN VOID                     *Context\r
-  )\r
-{\r
-}\r