]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
1. Fixed bugs in DxeNetLib to meet consistence with network module DriverBinding...
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitter.c
index d6c3abd9e245517b0abc4134eee9d2e2111de9ea..63be0b1d8b467a139545e0a3db3a7f531611f387 100644 (file)
@@ -43,6 +43,21 @@ STATIC TEXT_IN_SPLITTER_PRIVATE_DATA  mConIn = {
   0,\r
   (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,\r
   0,\r
+  {\r
+    ConSplitterTextInResetEx,\r
+    ConSplitterTextInReadKeyStrokeEx,\r
+    (EFI_EVENT) NULL,\r
+    ConSplitterTextInSetState,\r
+    ConSplitterTextInRegisterKeyNotify,\r
+    ConSplitterTextInUnregisterKeyNotify\r
+  },\r
+  0,\r
+  (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL,\r
+  0,\r
+  {\r
+    (struct _LIST_ENTRY     *) NULL,\r
+    (struct _LIST_ENTRY     *) NULL\r
+  },\r
 \r
   {\r
     ConSplitterSimplePointerReset,\r
@@ -61,6 +76,27 @@ STATIC TEXT_IN_SPLITTER_PRIVATE_DATA  mConIn = {
   (EFI_SIMPLE_POINTER_PROTOCOL **) NULL,\r
   0,\r
 \r
+  {\r
+    ConSplitterAbsolutePointerReset,\r
+    ConSplitterAbsolutePointerGetState,\r
+    (EFI_EVENT) NULL,\r
+    (EFI_ABSOLUTE_POINTER_MODE *) NULL\r
+  },\r
+\r
+  {\r
+    0,       //AbsoluteMinX\r
+    0,       //AbsoluteMinY\r
+    0,       //AbsoluteMinZ\r
+    0x10000, //AbsoluteMaxX\r
+    0x10000, //AbsoluteMaxY\r
+    0x10000, //AbsoluteMaxZ\r
+    0        //Attributes\r
+  },\r
+  0,\r
+  (EFI_ABSOLUTE_POINTER_PROTOCOL **) NULL,\r
+  0,\r
+  FALSE,\r
+\r
   FALSE,\r
   {\r
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
@@ -81,6 +117,19 @@ STATIC TEXT_IN_SPLITTER_PRIVATE_DATA  mConIn = {
   FALSE\r
 };\r
 \r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL gUgaDrawProtocolTemplate = {\r
+  ConSpliterUgaDrawGetMode,\r
+  ConSpliterUgaDrawSetMode,\r
+  ConSpliterUgaDrawBlt\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL gGraphicsOutputProtocolTemplate = {\r
+  ConSpliterGraphicsOutputQueryMode,\r
+  ConSpliterGraphicsOutputSetMode,\r
+  ConSpliterGraphicsOutputBlt,\r
+  NULL\r
+};\r
+\r
 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {\r
   TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
   (EFI_HANDLE) NULL,\r
@@ -105,9 +154,9 @@ STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
     FALSE,\r
   },\r
   {\r
-    ConSpliterUgaDrawGetMode,\r
-    ConSpliterUgaDrawSetMode,\r
-    ConSpliterUgaDrawBlt\r
+    NULL,\r
+    NULL,\r
+    NULL\r
   },\r
   0,\r
   0,\r
@@ -115,13 +164,14 @@ STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
   0,\r
   (EFI_UGA_PIXEL *) NULL,\r
   {\r
-    ConSpliterGraphicsOutputQueryMode,\r
-    ConSpliterGraphicsOutputSetMode,\r
-    ConSpliterGraphicsOutputBlt,\r
+    NULL,\r
+    NULL,\r
+    NULL,\r
     NULL\r
   },\r
   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
-  (TEXT_OUT_GOP_MODE *) NULL,\r
+  (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
+  0,\r
   0,\r
   TRUE,\r
   {\r
@@ -168,9 +218,9 @@ STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
     FALSE,\r
   },\r
   {\r
-    ConSpliterUgaDrawGetMode,\r
-    ConSpliterUgaDrawSetMode,\r
-    ConSpliterUgaDrawBlt\r
+    NULL,\r
+    NULL,\r
+    NULL\r
   },\r
   0,\r
   0,\r
@@ -178,13 +228,14 @@ STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
   0,\r
   (EFI_UGA_PIXEL *) NULL,\r
   {\r
-    ConSpliterGraphicsOutputQueryMode,\r
-    ConSpliterGraphicsOutputSetMode,\r
-    ConSpliterGraphicsOutputBlt,\r
+    NULL,\r
+    NULL,\r
+    NULL,\r
     NULL\r
   },\r
   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
-  (TEXT_OUT_GOP_MODE *) NULL,\r
+  (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
+  0,\r
   0,\r
   TRUE,\r
   {\r
@@ -225,6 +276,18 @@ EFI_DRIVER_BINDING_PROTOCOL           gConSplitterSimplePointerDriverBinding = {
   NULL\r
 };\r
 \r
+//\r
+// Driver binding instance for Absolute Pointer protocol\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL           gConSplitterAbsolutePointerDriverBinding = {\r
+  ConSplitterAbsolutePointerDriverBindingSupported,\r
+  ConSplitterAbsolutePointerDriverBindingStart,\r
+  ConSplitterAbsolutePointerDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
 EFI_DRIVER_BINDING_PROTOCOL           gConSplitterConOutDriverBinding = {\r
   ConSplitterConOutDriverBindingSupported,\r
   ConSplitterConOutDriverBindingStart,\r
@@ -285,6 +348,16 @@ InitializeConSplitter(
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gConSplitterAbsolutePointerDriverBinding,\r
+             NULL,\r
+             &gConSplitterAbsolutePointerComponentName,\r
+             &gConSplitterAbsolutePointerComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
              SystemTable,\r
@@ -367,8 +440,12 @@ Returns:
                     &mConIn.VirtualHandle,\r
                     &gEfiSimpleTextInProtocolGuid,\r
                     &mConIn.TextIn,\r
+                    &gEfiSimpleTextInputExProtocolGuid,\r
+                    &mConIn.TextInEx,\r
                     &gEfiSimplePointerProtocolGuid,\r
                     &mConIn.SimplePointer,\r
+                    &gEfiAbsolutePointerProtocolGuid,\r
+                    &mConIn.AbsolutePointer,\r
                     &gEfiPrimaryConsoleInDeviceGuid,\r
                     NULL,\r
                     NULL\r
@@ -514,6 +591,52 @@ Returns:
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // Buffer for Simple Text Input Ex Protocol\r
+  //\r
+  Status = ConSplitterGrowBuffer (\r
+             sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+             &ConInPrivate->TextInExListCount,\r
+             (VOID **) &ConInPrivate->TextInExList\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  ConSplitterTextInWaitForKey,\r
+                  ConInPrivate,\r
+                  &ConInPrivate->TextInEx.WaitForKeyEx\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  InitializeListHead (&ConInPrivate->NotifyList);\r
+\r
+  //\r
+  // Allocate Buffer and Create Event for Absolute Pointer and Simple Pointer Protocols\r
+  //\r
+  ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;\r
+\r
+  Status = ConSplitterGrowBuffer (\r
+            sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),\r
+            &ConInPrivate->AbsolutePointerListCount,\r
+            (VOID **) &ConInPrivate->AbsolutePointerList\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+            EVT_NOTIFY_WAIT,\r
+            TPL_NOTIFY,\r
+            ConSplitterAbsolutePointerWaitForInput,\r
+            ConInPrivate,\r
+            &ConInPrivate->AbsolutePointer.WaitForInput\r
+        );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;\r
 \r
   Status = ConSplitterGrowBuffer (\r
@@ -542,6 +665,18 @@ ConSplitterTextOutConstructor (
   )\r
 {\r
   EFI_STATUS  Status;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;\r
+\r
+  //\r
+  // Copy protocols template\r
+  //\r
+  if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+    CopyMem (&ConOutPrivate->UgaDraw, &gUgaDrawProtocolTemplate, sizeof (EFI_UGA_DRAW_PROTOCOL));\r
+  }\r
+\r
+  if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+    CopyMem (&ConOutPrivate->GraphicsOutput, &gGraphicsOutputProtocolTemplate, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL));\r
+  }\r
 \r
   //\r
   // Initilize console output splitter's private data.\r
@@ -590,21 +725,24 @@ ConSplitterTextOutConstructor (
     }\r
     //\r
     // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel\r
+    // DevNull will be updated to user-defined mode after driver has started.\r
     //\r
-    if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) {\r
+    if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-    ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800;\r
-    ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600;\r
+    Info = &ConOutPrivate->GraphicsOutputModeBuffer[0];\r
+    Info->Version = 0;\r
+    Info->HorizontalResolution = 800;\r
+    Info->VerticalResolution = 600;\r
+    Info->PixelFormat = PixelBltOnly;\r
+    Info->PixelsPerScanLine = 800;\r
+    CopyMem (ConOutPrivate->GraphicsOutput.Mode->Info, Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
+    ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
 \r
     //\r
     // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()\r
-    //  GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat\r
-    //  GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
+    // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
     //\r
-    ConOutPrivate->GraphicsOutput.Mode->Info->Version = 0;\r
-    ConOutPrivate->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
-    ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
     ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
     ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;\r
 \r
@@ -746,6 +884,36 @@ Returns:
           );\r
 }\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerDriverBindingSupported (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN  EFI_HANDLE                      ControllerHandle,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Absolute Pointer Supported Check\r
+\r
+Arguments:\r
+  This              - Pointer to protocol.\r
+  ControllerHandle  - Controller handle.\r
+  RemainingDevicePath  - Remaining device path.\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+\r
+--*/\r
+{\r
+  return ConSplitterSupported (\r
+          This,\r
+          ControllerHandle,\r
+          &gEfiAbsolutePointerProtocolGuid\r
+          );\r
+}\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 ConSplitterConOutDriverBindingSupported (\r
@@ -898,6 +1066,7 @@ Returns:
 {\r
   EFI_STATUS                     Status;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
 \r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
@@ -915,7 +1084,26 @@ Returns:
     return Status;\r
   }\r
 \r
-  return ConSplitterTextInAddDevice (&mConIn, TextIn);\r
+  Status = ConSplitterTextInAddDevice (&mConIn, TextIn);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  (VOID **) &TextInEx,\r
+                  This->DriverBindingHandle,\r
+                  mConIn.VirtualHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);\r
+\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
@@ -960,6 +1148,49 @@ Returns:
   return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);\r
 }\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerDriverBindingStart (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN  EFI_HANDLE                      ControllerHandle,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Start ConSplitter on ControllerHandle, and create the virtual\r
+  agrogated console device on first call Start for a ConIn handle.\r
+\r
+Arguments:\r
+  This                 - Pointer to protocol.\r
+  ControllerHandle     - Controller handle.\r
+  RemainingDevicePath  - Remaining device path.\r
+\r
+Returns:\r
+\r
+  EFI_ERROR if a AbsolutePointer protocol is not started.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer;\r
+\r
+  Status = ConSplitterStart (\r
+             This,\r
+             ControllerHandle,\r
+             mConIn.VirtualHandle,\r
+             &gEfiAbsolutePointerProtocolGuid,\r
+             &gEfiAbsolutePointerProtocolGuid,\r
+             (VOID **) &AbsolutePointer\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return ConSplitterAbsolutePointerAddDevice (&mConIn, AbsolutePointer);\r
+}\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 ConSplitterConOutDriverBindingStart (\r
@@ -1195,10 +1426,29 @@ Returns:
   EFI_STATUS                     Status;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
 \r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
   if (NumberOfChildren == 0) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  (VOID **) &TextInEx,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+\r
   Status = ConSplitterStop (\r
             This,\r
             ControllerHandle,\r
@@ -1261,6 +1511,51 @@ Returns:
   return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);\r
 }\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN  EFI_HANDLE                      ControllerHandle,\r
+  IN  UINTN                           NumberOfChildren,\r
+  IN  EFI_HANDLE                      *ChildHandleBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+  (Standard DriverBinding Protocol Stop() function)\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = ConSplitterStop (\r
+             This,\r
+             ControllerHandle,\r
+             mConIn.VirtualHandle,\r
+             &gEfiAbsolutePointerProtocolGuid,\r
+             &gEfiAbsolutePointerProtocolGuid,\r
+             (VOID **) &AbsolutePointer\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Delete this console input device's data structures.\r
+  //\r
+  return ConSplitterAbsolutePointerDeleteDevice (&mConIn, AbsolutePointer);\r
+}\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 ConSplitterConOutDriverBindingStop (\r
@@ -1512,6 +1807,66 @@ Returns:
   return EFI_NOT_FOUND;\r
 }\r
 \r
+EFI_STATUS\r
+ConSplitterTextInExAddDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // If the TextInEx List is full, enlarge it by calling growbuffer().\r
+  //\r
+  if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
+    Status = ConSplitterGrowBuffer (\r
+              sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+              &Private->TextInExListCount,\r
+              (VOID **) &Private->TextInExList\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+  //\r
+  // Add the new text-in device data structure into the Text In List.\r
+  //\r
+  Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
+  Private->CurrentNumberOfExConsoles++;\r
+\r
+  //\r
+  // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
+  //\r
+  gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConSplitterTextInExDeleteDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
+  )\r
+{\r
+  UINTN Index;\r
+  //\r
+  // Remove the specified text-in device data structure from the Text In List,\r
+  // and rearrange the remaining data structures in the Text In List.\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    if (Private->TextInExList[Index] == TextInEx) {\r
+      for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
+        Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
+      }\r
+\r
+      Private->CurrentNumberOfExConsoles--;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
 EFI_STATUS\r
 ConSplitterSimplePointerAddDevice (\r
   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
@@ -1589,10 +1944,10 @@ Returns:
   return EFI_NOT_FOUND;\r
 }\r
 \r
-STATIC\r
 EFI_STATUS\r
-ConSplitterGrowMapTable (\r
-  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private\r
+ConSplitterAbsolutePointerAddDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA     *Private,\r
+  IN  EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer\r
   )\r
 /*++\r
 \r
@@ -1602,17 +1957,94 @@ Arguments:
 \r
 Returns:\r
 \r
-  None\r
+  EFI_OUT_OF_RESOURCES\r
+  EFI_SUCCESS\r
 \r
 --*/\r
 {\r
-  UINTN Size;\r
-  UINTN NewSize;\r
-  UINTN TotalSize;\r
-  INT32 *TextOutModeMap;\r
-  INT32 *OldTextOutModeMap;\r
-  INT32 *SrcAddress;\r
-  INT32 Index;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // If the Absolute Pointer List is full, enlarge it by calling growbuffer().\r
+  //\r
+  if (Private->CurrentNumberOfAbsolutePointers >= Private->AbsolutePointerListCount) {\r
+    Status = ConSplitterGrowBuffer (\r
+              sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),\r
+              &Private->AbsolutePointerListCount,\r
+              (VOID **) &Private->AbsolutePointerList\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+  //\r
+  // Add the new text-in device data structure into the Text In List.\r
+  //\r
+  Private->AbsolutePointerList[Private->CurrentNumberOfAbsolutePointers] = AbsolutePointer;\r
+  Private->CurrentNumberOfAbsolutePointers++;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConSplitterAbsolutePointerDeleteDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA     *Private,\r
+  IN  EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN Index;\r
+  //\r
+  // Remove the specified text-in device data structure from the Text In List,\r
+  // and rearrange the remaining data structures in the Text In List.\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+    if (Private->AbsolutePointerList[Index] == AbsolutePointer) {\r
+      for (Index = Index; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
+        Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];\r
+      }\r
+\r
+      Private->CurrentNumberOfAbsolutePointers--;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+ConSplitterGrowMapTable (\r
+  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN Size;\r
+  UINTN NewSize;\r
+  UINTN TotalSize;\r
+  INT32 *TextOutModeMap;\r
+  INT32 *OldTextOutModeMap;\r
+  INT32 *SrcAddress;\r
+  INT32 Index;\r
 \r
   NewSize           = Private->TextOutListCount * sizeof (INT32);\r
   OldTextOutModeMap = Private->TextOutModeMap;\r
@@ -1811,6 +2243,7 @@ Returns:
   INT32                         Index;\r
   INT32                         *TextOutModeMap;\r
   INT32                         *MapTable;\r
+  INT32                         QueryMode;\r
   TEXT_OUT_SPLITTER_QUERY_DATA  *TextOutQueryData;\r
   UINTN                         Rows;\r
   UINTN                         Columns;\r
@@ -1831,13 +2264,15 @@ Returns:
   MapTable  = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
   while (Mode < TextOut->Mode->MaxMode) {\r
     TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
+        MapTable[StepSize] = Mode;\r
 \r
     //\r
-    // Search the QueryData database to see if they intersects\r
+    // Search the intersection map and QueryData database to see if they intersects\r
     //\r
     Index = 0;\r
     while (Index < CurrentMaxMode) {\r
-      if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {\r
+      QueryMode = *(TextOutModeMap + Index * StepSize);\r
+      if ((TextOutQueryData[QueryMode].Rows == Rows) && (TextOutQueryData[QueryMode].Columns == Columns)) {\r
         MapTable[Index * StepSize] = Mode;\r
         break;\r
       }\r
@@ -1876,7 +2311,7 @@ Arguments:
 \r
 Returns:\r
 \r
-  None\r
+  EFI_SUCCESS\r
   EFI_OUT_OF_RESOURCES\r
 \r
 --*/\r
@@ -1887,10 +2322,14 @@ Returns:
   TEXT_OUT_AND_GOP_DATA         *StdErrTextOutList;\r
   UINTN                         Indexi;\r
   UINTN                         Indexj;\r
-  UINTN                         Rows;\r
-  UINTN                         Columns;\r
+  UINTN                         ConOutRows;\r
+  UINTN                         ConOutColumns;\r
+  UINTN                         StdErrRows;\r
+  UINTN                         StdErrColumns;\r
   INT32                         ConOutMaxMode;\r
   INT32                         StdErrMaxMode;\r
+  INT32                         ConOutMode;\r
+  INT32                         StdErrMode;\r
   INT32                         Mode;\r
   INT32                         Index;\r
   INT32                         *ConOutModeMap;\r
@@ -1899,6 +2338,8 @@ Returns:
   INT32                         *StdErrMapTable;\r
   TEXT_OUT_SPLITTER_QUERY_DATA  *ConOutQueryData;\r
   TEXT_OUT_SPLITTER_QUERY_DATA  *StdErrQueryData;\r
+  UINTN                         ConOutStepSize;\r
+  UINTN                         StdErrStepSize;\r
   BOOLEAN                       FoundTheSameTextOut;\r
   UINTN                         ConOutMapTableSize;\r
   UINTN                         StdErrMapTableSize;\r
@@ -1934,10 +2375,12 @@ Returns:
   //\r
   ConOutMaxMode     = mConOut.TextOutMode.MaxMode;\r
   ConOutModeMap     = mConOut.TextOutModeMap;\r
+  ConOutStepSize    = mConOut.TextOutListCount;\r
   ConOutQueryData   = mConOut.TextOutQueryData;\r
 \r
   StdErrMaxMode     = mStdErr.TextOutMode.MaxMode;\r
   StdErrModeMap     = mStdErr.TextOutModeMap;\r
+  StdErrStepSize    = mStdErr.TextOutListCount;\r
   StdErrQueryData   = mStdErr.TextOutQueryData;\r
 \r
   //\r
@@ -1966,13 +2409,17 @@ Returns:
   Mode = 0;\r
   while (Mode < ConOutMaxMode) {\r
     //\r
-    // Search the other's QueryData database to see if they intersect\r
+    // Search the intersection map and QueryData database to see if they intersect\r
     //\r
-    Index   = 0;\r
-    Rows    = ConOutQueryData[Mode].Rows;\r
-    Columns = ConOutQueryData[Mode].Columns;\r
+    Index = 0;\r
+    ConOutMode    = *(ConOutModeMap + Mode * ConOutStepSize);\r
+    ConOutRows    = ConOutQueryData[ConOutMode].Rows;\r
+    ConOutColumns = ConOutQueryData[ConOutMode].Columns;\r
     while (Index < StdErrMaxMode) {\r
-      if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {\r
+      StdErrMode    = *(StdErrModeMap + Index * StdErrStepSize);\r
+      StdErrRows    = StdErrQueryData[StdErrMode].Rows;\r
+      StdErrColumns = StdErrQueryData[StdErrMode].Columns;\r
+      if ((StdErrRows == ConOutRows) && (StdErrColumns == ConOutColumns)) {\r
         ConOutMapTable[Mode]  = 1;\r
         StdErrMapTable[Index] = 1;\r
         break;\r
@@ -2038,14 +2485,20 @@ Returns:
 {\r
   EFI_STATUS                           Status;\r
   UINTN                                Index;\r
-  TEXT_OUT_GOP_MODE                    *Mode;\r
+  UINTN                                CurrentIndex;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;\r
   UINTN                                SizeOfInfo;\r
   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
   EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE    *CurrentGraphicsOutputMode;\r
-  TEXT_OUT_GOP_MODE                    *ModeBuffer;\r
-  TEXT_OUT_GOP_MODE                    *MatchedMode;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeBuffer;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MatchedMode;\r
   UINTN                                NumberIndex;\r
   BOOLEAN                              Match;\r
+  BOOLEAN                              AlreadyExist;\r
+  UINT32                               UgaHorizontalResolution;\r
+  UINT32                               UgaVerticalResolution;\r
+  UINT32                               UgaColorDepth;\r
+  UINT32                               UgaRefreshRate;\r
 \r
   if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
     return EFI_UNSUPPORTED;\r
@@ -2053,6 +2506,18 @@ Returns:
 \r
   CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;\r
 \r
+  Index        = 0;\r
+  CurrentIndex = 0;\r
+\r
+  if (Private->CurrentNumberOfUgaDraw != 0) {\r
+    //\r
+    // If any UGA device has already been added, then there is no need to\r
+    // calculate intersection of display mode of different GOP/UGA device,\r
+    // since only one display mode will be exported (i.e. user-defined mode)\r
+    //\r
+    goto Done;\r
+  }\r
+\r
   if (GraphicsOutput != NULL) {\r
     if (Private->CurrentNumberOfGraphicsOutput == 0) {\r
         //\r
@@ -2068,7 +2533,7 @@ Returns:
         //\r
         // Allocate resource for the private mode buffer\r
         //\r
-        ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode);\r
+        ModeBuffer = AllocatePool (GraphicsOutput->Mode->SizeOfInfo * GraphicsOutput->Mode->MaxMode);\r
         if (ModeBuffer == NULL) {\r
           return EFI_OUT_OF_RESOURCES;\r
         }\r
@@ -2084,8 +2549,7 @@ Returns:
           if (EFI_ERROR (Status)) {\r
             return Status;\r
           }\r
-          Mode->HorizontalResolution = Info->HorizontalResolution;\r
-          Mode->VerticalResolution = Info->VerticalResolution;\r
+          CopyMem (Mode, Info, SizeOfInfo);\r
           Mode++;\r
           FreePool (Info);\r
         }\r
@@ -2093,7 +2557,7 @@ Returns:
       //\r
       // Check intersection of display mode\r
       //\r
-      ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode);\r
+      ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * CurrentGraphicsOutputMode->MaxMode);\r
       if (ModeBuffer == NULL) {\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
@@ -2109,7 +2573,7 @@ Returns:
             return Status;\r
           }\r
           if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
-              (Info->VerticalResolution == Mode->VerticalResolution)){\r
+              (Info->VerticalResolution == Mode->VerticalResolution)) {\r
             Match = TRUE;\r
             FreePool (Info);\r
             break;\r
@@ -2118,8 +2582,28 @@ Returns:
         }\r
 \r
         if (Match) {\r
-          CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE));\r
-          MatchedMode++;\r
+          AlreadyExist = FALSE;\r
+\r
+          for (Info = ModeBuffer; Info < MatchedMode; Info++) {\r
+            if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
+                (Info->VerticalResolution == Mode->VerticalResolution)) {\r
+              AlreadyExist = TRUE;\r
+              break;\r
+            }\r
+          }\r
+\r
+          if (!AlreadyExist) {\r
+            CopyMem (MatchedMode, Mode, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
+\r
+            //\r
+            // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly\r
+            //\r
+            MatchedMode->Version = 0;\r
+            MatchedMode->PixelFormat = PixelBltOnly;\r
+            ZeroMem (&MatchedMode->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
+\r
+            MatchedMode++;\r
+          }\r
         }\r
 \r
         Mode++;\r
@@ -2134,7 +2618,7 @@ Returns:
       //\r
       // Physical frame buffer is no longer available when there are more than one physical GOP devices\r
       //\r
-      CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE));\r
+      CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
       CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
       ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
       CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
@@ -2143,36 +2627,49 @@ Returns:
     }\r
 \r
     //\r
-    // Select a prefered Display mode 800x600\r
+    // Graphics console driver can ensure the same mode for all GOP devices\r
     //\r
     for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
       Mode = &Private->GraphicsOutputModeBuffer[Index];\r
-      if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
+      if ((Mode->HorizontalResolution == GraphicsOutput->Mode->Info->HorizontalResolution) &&\r
+         (Mode->VerticalResolution == GraphicsOutput->Mode->Info->VerticalResolution)) {\r
+        CurrentIndex = Index;\r
         break;\r
       }\r
     }\r
-    //\r
-    // Prefered mode is not found, set to mode 0\r
-    //\r
     if (Index >= CurrentGraphicsOutputMode->MaxMode) {\r
-      Index = 0;\r
+      //\r
+      // if user defined mode is not found, set to default mode 800x600\r
+      //\r
+      for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
+        Mode = &Private->GraphicsOutputModeBuffer[Index];\r
+        if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
+          CurrentIndex = Index;\r
+          break;\r
+        }\r
+      }\r
     }\r
-\r
-    //\r
-    // Current mode number may need update now, so set it to an invalide mode number\r
-    //\r
-    CurrentGraphicsOutputMode->Mode = 0xffff;\r
-  } else {\r
+  }\r
+  if (UgaDraw != NULL) {\r
     //\r
-    // For UGA device, it's inconvenient to retrieve all the supported display modes.\r
-    // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec\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
     //\r
+    UgaDraw->GetMode (\r
+               UgaDraw,\r
+               &UgaHorizontalResolution,\r
+               &UgaVerticalResolution,\r
+               &UgaColorDepth,\r
+               &UgaRefreshRate\r
+               );\r
+\r
     CurrentGraphicsOutputMode->MaxMode = 1;\r
-    CurrentGraphicsOutputMode->Info->Version = 0;\r
-    CurrentGraphicsOutputMode->Info->HorizontalResolution = 800;\r
-    CurrentGraphicsOutputMode->Info->VerticalResolution = 600;\r
-    CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
-    CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800;\r
+    Info = CurrentGraphicsOutputMode->Info;\r
+    Info->Version = 0;\r
+    Info->HorizontalResolution = UgaHorizontalResolution;\r
+    Info->VerticalResolution = UgaVerticalResolution;\r
+    Info->PixelFormat = PixelBltOnly;\r
+    Info->PixelsPerScanLine = UgaHorizontalResolution;\r
     CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
     CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
     CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
@@ -2180,15 +2677,21 @@ Returns:
     //\r
     // Update the private mode buffer\r
     //\r
-    ModeBuffer = &Private->GraphicsOutputModeBuffer[0];\r
-    ModeBuffer->HorizontalResolution = 800;\r
-    ModeBuffer->VerticalResolution   = 600;\r
+    CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
 \r
     //\r
-    // Current mode is unknow now, set it to an invalid mode number 0xffff\r
+    // Only mode 0 is available to be set\r
     //\r
-    CurrentGraphicsOutputMode->Mode = 0xffff;\r
-    Index = 0;\r
+    CurrentIndex = 0;\r
+  }\r
+\r
+Done:\r
+\r
+  if (GraphicsOutput != NULL) {\r
+    Private->CurrentNumberOfGraphicsOutput++;\r
+  }\r
+  if (UgaDraw != NULL) {\r
+    Private->CurrentNumberOfUgaDraw++;\r
   }\r
 \r
   //\r
@@ -2196,9 +2699,23 @@ Returns:
   // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
   //\r
   Private->HardwareNeedsStarting = TRUE;\r
-  Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);\r
+  //\r
+  // Current mode number may need update now, so set it to an invalid mode number\r
+  //\r
+  CurrentGraphicsOutputMode->Mode = 0xffff;\r
+  //\r
+  // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.\r
+  //\r
+  Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex);\r
 \r
-  Private->CurrentNumberOfGraphicsOutput++;\r
+  //\r
+  // If user defined mode is not valid for UGA, set to the default mode 800x600.\r
+  //\r
+  if (EFI_ERROR(Status)) {\r
+    (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800;\r
+    (Private->GraphicsOutputModeBuffer[0]).VerticalResolution   = 600;\r
+    Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -2226,6 +2743,10 @@ Returns:
   UINTN                 CurrentNumOfConsoles;\r
   INT32                 CurrentMode;\r
   INT32                 MaxMode;\r
+  UINT32                UgaHorizontalResolution;\r
+  UINT32                UgaVerticalResolution;\r
+  UINT32                UgaColorDepth;\r
+  UINT32                UgaRefreshRate;\r
   TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
 \r
   Status                = EFI_SUCCESS;\r
@@ -2260,12 +2781,12 @@ Returns:
 \r
   if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
     //\r
-    // If No UGA device then use the ConOut device\r
+    // If No GOP/UGA device then use the ConOut device\r
     //\r
     TextAndGop->TextOutEnabled = TRUE;\r
   } else {\r
     //\r
-    // If UGA device use ConOut device only used if UGA screen is in Text mode\r
+    // If GOP/UGA device use ConOut device only used if screen is in Text mode\r
     //\r
     TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);\r
   }\r
@@ -2292,15 +2813,50 @@ Returns:
   MaxMode     = Private->TextOutMode.MaxMode;\r
   ASSERT (MaxMode >= 1);\r
 \r
+  //\r
+  // Update DevNull mode according to current video device\r
+  //\r
   if (FeaturePcdGet (PcdConOutGopSupport)) {\r
     if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
       ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
     }\r
   }\r
+  if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+    if (UgaDraw != NULL) {\r
+      Status = UgaDraw->GetMode (\r
+                    UgaDraw,\r
+                    &UgaHorizontalResolution,\r
+                    &UgaVerticalResolution,\r
+                    &UgaColorDepth,\r
+                    &UgaRefreshRate\r
+                    );\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = ConSpliterUgaDrawSetMode (\r
+                    &Private->UgaDraw,\r
+                    UgaHorizontalResolution,\r
+                    UgaVerticalResolution,\r
+                    UgaColorDepth,\r
+                    UgaRefreshRate\r
+                    );\r
+      }\r
+      //\r
+      // If GetMode/SetMode is failed, set to 800x600 mode\r
+      //\r
+      if(EFI_ERROR (Status)) {\r
+        Status = ConSpliterUgaDrawSetMode (\r
+                    &Private->UgaDraw,\r
+                    800,\r
+                    600,\r
+                    32,\r
+                    60\r
+                    );\r
+      }\r
+    }\r
+  }\r
 \r
   if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {\r
     //\r
-    // We just added a new UGA device in graphics mode\r
+    // We just added a new GOP or UGA device in graphics mode\r
     //\r
     if (FeaturePcdGet (PcdConOutGopSupport)) {\r
       DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
@@ -2311,7 +2867,7 @@ Returns:
     //\r
     // The new console supports the same mode of the current console so sync up\r
     //\r
-    DevNullSyncGopStdOut (Private);\r
+    DevNullSyncStdOut (Private);\r
   } else {\r
     //\r
     // If ConOut, then set the mode to Mode #0 which us 80 x 25\r
@@ -2355,6 +2911,12 @@ Returns:
     if (TextOutList->TextOut == TextOut) {\r
       CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
       CurrentNumOfConsoles--;\r
+      if (TextOutList->UgaDraw != NULL) {\r
+        Private->CurrentNumberOfUgaDraw--;\r
+      }\r
+      if (TextOutList->GraphicsOutput != NULL) {\r
+        Private->CurrentNumberOfGraphicsOutput--;\r
+      }\r
       break;\r
     }\r
 \r
@@ -2760,11 +3322,62 @@ Returns:
   }\r
 }\r
 \r
+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  RegsiteredData    - A pointer to a buffer that is filled in with the keystroke\r
+                      state data for the key that was registered.\r
+  InputData         - A pointer to a buffer that is filled in with the keystroke\r
+                      state data for the key that was pressed.\r
+\r
+Returns:\r
+  TRUE              - Key be pressed matches a registered key.\r
+  FLASE             - Match failed.\r
+\r
+--*/\r
+{\r
+  ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+\r
+  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||\r
+      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+  //\r
+  if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+      RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+    return FALSE;\r
+  }\r
+  if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+      RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+\r
 EFI_STATUS\r
 EFIAPI\r
-ConSplitterSimplePointerReset (\r
-  IN  EFI_SIMPLE_POINTER_PROTOCOL     *This,\r
-  IN  BOOLEAN                         ExtendedVerification\r
+ConSplitterTextInResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
   )\r
 /*++\r
 \r
@@ -2787,35 +3400,32 @@ ConSplitterSimplePointerReset (
   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
   UINTN                         Index;\r
 \r
-  Private                         = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
+  Private                       = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
-  Private->InputEventSignalState  = FALSE;\r
+  Private->KeyEventSignalState  = FALSE;\r
 \r
-  if (Private->CurrentNumberOfPointers == 0) {\r
-    return EFI_SUCCESS;\r
-  }\r
   //\r
   // return the worst status met\r
   //\r
-  for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {\r
-    Status = Private->PointerList[Index]->Reset (\r
-                                            Private->PointerList[Index],\r
-                                            ExtendedVerification\r
-                                            );\r
+  for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->Reset (\r
+                                             Private->TextInExList[Index],\r
+                                             ExtendedVerification\r
+                                             );\r
     if (EFI_ERROR (Status)) {\r
       ReturnStatus = Status;\r
     }\r
   }\r
 \r
   return ReturnStatus;\r
+\r
 }\r
 \r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
-ConSplitterSimplePointerPrivateGetState (\r
-  IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
-  IN OUT EFI_SIMPLE_POINTER_STATE     *State\r
+ConSplitterTextInReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
   )\r
 /*++\r
 \r
@@ -2824,102 +3434,479 @@ ConSplitterSimplePointerPrivateGetState (
     be used to test for existance of a keystroke via WaitForEvent () call.\r
 \r
   Arguments:\r
-    This   - Protocol instance pointer.\r
-    State  -\r
+    This       - Protocol instance pointer.\r
+    KeyData    - A pointer to a buffer that is filled in with the keystroke\r
+                 state data for the key that was pressed.\r
 \r
   Returns:\r
-    EFI_SUCCESS       - The keystroke information was returned.\r
-    EFI_NOT_READY     - There was no keystroke data availiable.\r
-    EFI_DEVICE_ERROR  - The keydtroke information was not returned due to\r
-                        hardware errors.\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to\r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.\r
 \r
 --*/\r
 {\r
-  EFI_STATUS                Status;\r
-  EFI_STATUS                ReturnStatus;\r
-  UINTN                     Index;\r
-  EFI_SIMPLE_POINTER_STATE  CurrentState;\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  EFI_KEY_DATA                  CurrentKeyData;\r
 \r
-  State->RelativeMovementX  = 0;\r
-  State->RelativeMovementY  = 0;\r
-  State->RelativeMovementZ  = 0;\r
-  State->LeftButton         = FALSE;\r
-  State->RightButton        = FALSE;\r
+\r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+  if (Private->PasswordEnabled) {\r
+    //\r
+    // If StdIn Locked return not ready\r
+    //\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Private->KeyEventSignalState = FALSE;\r
+\r
+  KeyData->Key.UnicodeChar  = 0;\r
+  KeyData->Key.ScanCode     = SCAN_NULL;\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
   //\r
-  ReturnStatus = EFI_NOT_READY;\r
-  for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
-\r
-    Status = Private->PointerList[Index]->GetState (\r
-                                            Private->PointerList[Index],\r
-                                            &CurrentState\r
-                                            );\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
+                                          Private->TextInExList[Index],\r
+                                          &CurrentKeyData\r
+                                          );\r
     if (!EFI_ERROR (Status)) {\r
-      if (ReturnStatus == EFI_NOT_READY) {\r
-        ReturnStatus = EFI_SUCCESS;\r
-      }\r
-\r
-      if (CurrentState.LeftButton) {\r
-        State->LeftButton = TRUE;\r
-      }\r
-\r
-      if (CurrentState.RightButton) {\r
-        State->RightButton = TRUE;\r
-      }\r
-\r
-      if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {\r
-        State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;\r
-      }\r
-\r
-      if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {\r
-        State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;\r
-      }\r
-\r
-      if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {\r
-        State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;\r
-      }\r
-    } else if (Status == EFI_DEVICE_ERROR) {\r
-      ReturnStatus = EFI_DEVICE_ERROR;\r
+      CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
+      return Status;\r
     }\r
   }\r
 \r
-  return ReturnStatus;\r
+  return EFI_NOT_READY;\r
 }\r
 \r
 EFI_STATUS\r
 EFIAPI\r
-ConSplitterSimplePointerGetState (\r
-  IN  EFI_SIMPLE_POINTER_PROTOCOL     *This,\r
-  IN OUT EFI_SIMPLE_POINTER_STATE     *State\r
+ConSplitterTextInSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
   )\r
 /*++\r
 \r
   Routine Description:\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
-    If the ConIn is password locked make it look like no keystroke is availible\r
+    Set certain state for the input device.\r
 \r
   Arguments:\r
-    This   - Protocol instance pointer.\r
-    State  -\r
+    This                  - Protocol instance pointer.\r
+    KeyToggleState        - A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
+                            state for the input device.\r
 \r
   Returns:\r
-    EFI_SUCCESS       - The keystroke information was returned.\r
-    EFI_NOT_READY     - There was no keystroke data availiable.\r
-    EFI_DEVICE_ERROR  - The keydtroke information was not returned due to\r
-                        hardware errors.\r
+    EFI_SUCCESS           - The device state was set successfully.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could\r
+                            not have the setting adjusted.\r
+    EFI_UNSUPPORTED       - The device does not have the ability to set its state.\r
+    EFI_INVALID_PARAMETER - KeyToggleState is NULL.\r
 \r
 --*/\r
 {\r
   TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
 \r
-  Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
-  if (Private->PasswordEnabled) {\r
-    //\r
+  if (KeyToggleState == NULL) {\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, return EFI_SUCCESS;\r
+  // otherwise return the status of setting state of physical console input device\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->SetState (\r
+                                             Private->TextInExList[Index],\r
+                                             KeyToggleState\r
+                                             );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInRegisterKeyNotify (\r
+  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
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Register a notification function for a particular keystroke for the input device.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    KeyData                 - A pointer to a buffer that is filled in with the keystroke\r
+                              information data for the key that was pressed.\r
+    KeyNotificationFunction - Points to the function to be called when the key\r
+                              sequence is typed specified by KeyData.\r
+    NotifyHandle            - Points to the unique handle assigned to the registered notification.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was registered successfully.\r
+    EFI_OUT_OF_RESOURCES    - Unable to allocate resources for necesssary data structures.\r
+    EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.\r
+\r
+--*/\r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  TEXT_IN_EX_SPLITTER_NOTIFY    *NewNotify;\r
+  LIST_ENTRY                    *Link;\r
+  TEXT_IN_EX_SPLITTER_NOTIFY    *CurrentNotify;\r
+\r
+\r
+  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\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
+  //\r
+  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+  //\r
+  for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link,\r
+                      TEXT_IN_EX_SPLITTER_NOTIFY,\r
+                      NotifyEntry,\r
+                      TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
+                      );\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
+      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+        *NotifyHandle = CurrentNotify->NotifyHandle;\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Allocate resource to save the notification function\r
+  //\r
+  NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
+  if (NewNotify == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\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
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+\r
+  //\r
+  // Return the wrong status of registering key notify of\r
+  // physical console input device if meet problems\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
+                                             Private->TextInExList[Index],\r
+                                             KeyData,\r
+                                             KeyNotificationFunction,\r
+                                             &NewNotify->NotifyHandleList[Index]\r
+                                             );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->FreePool (NewNotify->NotifyHandleList);\r
+      gBS->FreePool (NewNotify);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &NewNotify->NotifyHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+\r
+  *NotifyHandle                = NewNotify->NotifyHandle;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Remove a registered notification function from a particular keystroke.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    NotificationHandle      - The handle of the notification function being unregistered.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was unregistered successfully.\r
+    EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.\r
+    EFI_NOT_FOUND           - Can not find the matching entry in database.\r
+\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
+\r
+  if (NotificationHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  NotificationHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\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 = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
+    if (CurrentNotify->NotifyHandle == 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
+      }\r
+      RemoveEntryList (&CurrentNotify->NotifyEntry);\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      CurrentNotify->NotifyHandle,\r
+                      &gSimpleTextInExNotifyGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+      gBS->FreePool (CurrentNotify->NotifyHandleList);\r
+      gBS->FreePool (CurrentNotify);\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterSimplePointerReset (\r
+  IN  EFI_SIMPLE_POINTER_PROTOCOL     *This,\r
+  IN  BOOLEAN                         ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the input device and optionaly run diagnostics\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could\r
+                            not be reset.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_STATUS                    ReturnStatus;\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  UINTN                         Index;\r
+\r
+  Private                         = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
+\r
+  Private->InputEventSignalState  = FALSE;\r
+\r
+  if (Private->CurrentNumberOfPointers == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // return the worst status met\r
+  //\r
+  for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {\r
+    Status = Private->PointerList[Index]->Reset (\r
+                                            Private->PointerList[Index],\r
+                                            ExtendedVerification\r
+                                            );\r
+    if (EFI_ERROR (Status)) {\r
+      ReturnStatus = Status;\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterSimplePointerPrivateGetState (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
+  IN OUT EFI_SIMPLE_POINTER_STATE     *State\r
+  )\r
+/*++\r
+\r
+  Routine Description:\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
+\r
+  Arguments:\r
+    This   - Protocol instance pointer.\r
+    State  -\r
+\r
+  Returns:\r
+    EFI_SUCCESS       - The keystroke information was returned.\r
+    EFI_NOT_READY     - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR  - The keydtroke information was not returned due to\r
+                        hardware errors.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_STATUS                ReturnStatus;\r
+  UINTN                     Index;\r
+  EFI_SIMPLE_POINTER_STATE  CurrentState;\r
+\r
+  State->RelativeMovementX  = 0;\r
+  State->RelativeMovementY  = 0;\r
+  State->RelativeMovementZ  = 0;\r
+  State->LeftButton         = FALSE;\r
+  State->RightButton        = FALSE;\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
+  //\r
+  ReturnStatus = EFI_NOT_READY;\r
+  for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
+\r
+    Status = Private->PointerList[Index]->GetState (\r
+                                            Private->PointerList[Index],\r
+                                            &CurrentState\r
+                                            );\r
+    if (!EFI_ERROR (Status)) {\r
+      if (ReturnStatus == EFI_NOT_READY) {\r
+        ReturnStatus = EFI_SUCCESS;\r
+      }\r
+\r
+      if (CurrentState.LeftButton) {\r
+        State->LeftButton = TRUE;\r
+      }\r
+\r
+      if (CurrentState.RightButton) {\r
+        State->RightButton = TRUE;\r
+      }\r
+\r
+      if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {\r
+        State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;\r
+      }\r
+\r
+      if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {\r
+        State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;\r
+      }\r
+\r
+      if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {\r
+        State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;\r
+      }\r
+    } else if (Status == EFI_DEVICE_ERROR) {\r
+      ReturnStatus = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterSimplePointerGetState (\r
+  IN  EFI_SIMPLE_POINTER_PROTOCOL     *This,\r
+  IN OUT EFI_SIMPLE_POINTER_STATE     *State\r
+  )\r
+/*++\r
+\r
+  Routine Description:\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
+    If the ConIn is password locked make it look like no keystroke is availible\r
+\r
+  Arguments:\r
+    This   - Protocol instance pointer.\r
+    State  -\r
+\r
+  Returns:\r
+    EFI_SUCCESS       - The keystroke information was returned.\r
+    EFI_NOT_READY     - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR  - The keydtroke information was not returned due to\r
+                        hardware errors.\r
+\r
+--*/\r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+\r
+  Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
+  if (Private->PasswordEnabled) {\r
+    //\r
     // If StdIn Locked return not ready\r
     //\r
     return EFI_NOT_READY;\r
@@ -2985,6 +3972,198 @@ Returns:
   }\r
 }\r
 \r
+//\r
+// Absolute Pointer Protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerReset (\r
+  IN EFI_ABSOLUTE_POINTER_PROTOCOL   *This,\r
+  IN BOOLEAN                         ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Resets the pointer device hardware.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    ExtendedVerification  - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could\r
+                            not be reset.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_STATUS                    ReturnStatus;\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  UINTN                         Index;\r
+\r
+  Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
+\r
+  Private->AbsoluteInputEventSignalState = FALSE;\r
+\r
+  if (Private->CurrentNumberOfAbsolutePointers == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // return the worst status met\r
+  //\r
+  for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+    Status = Private->AbsolutePointerList[Index]->Reset (\r
+                                                    Private->AbsolutePointerList[Index],\r
+                                                    ExtendedVerification\r
+                                                    );\r
+    if (EFI_ERROR (Status)) {\r
+      ReturnStatus = Status;\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerGetState (\r
+  IN EFI_ABSOLUTE_POINTER_PROTOCOL   *This,\r
+  IN OUT EFI_ABSOLUTE_POINTER_STATE  *State\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves the current state of a pointer device.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    State                 - A pointer to the state information on the pointer device.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The state of the pointer device was returned in State..\r
+    EFI_NOT_READY         - The state of the pointer device has not changed since the last call to\r
+                            GetState().\r
+    EFI_DEVICE_ERROR      - A device error occurred while attempting to retrieve the pointer\r
+                            device's current state.\r
+--*/\r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  EFI_STATUS                    ReturnStatus;\r
+  UINTN                         Index;\r
+  EFI_ABSOLUTE_POINTER_STATE    CurrentState;\r
+\r
+\r
+  Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
+  if (Private->PasswordEnabled) {\r
+    //\r
+    // If StdIn Locked return not ready\r
+    //\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Private->AbsoluteInputEventSignalState = FALSE;\r
+\r
+  State->CurrentX                        = 0;\r
+  State->CurrentY                        = 0;\r
+  State->CurrentZ                        = 0;\r
+  State->ActiveButtons                   = 0;\r
+\r
+  //\r
+  // if no physical pointer device exists, return EFI_NOT_READY;\r
+  // if any physical pointer device has changed state,\r
+  // return the state and EFI_SUCCESS.\r
+  //\r
+  ReturnStatus = EFI_NOT_READY;\r
+  for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+\r
+    Status = Private->AbsolutePointerList[Index]->GetState (\r
+                                                    Private->AbsolutePointerList[Index],\r
+                                                    &CurrentState\r
+                                                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      if (ReturnStatus == EFI_NOT_READY) {\r
+        ReturnStatus = EFI_SUCCESS;\r
+      }\r
+\r
+      State->ActiveButtons = CurrentState.ActiveButtons;\r
+\r
+      if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {\r
+        State->CurrentX = CurrentState.CurrentX;\r
+      }\r
+      if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {\r
+        State->CurrentY = CurrentState.CurrentY;\r
+      }\r
+      if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {\r
+        State->CurrentZ = CurrentState.CurrentZ;\r
+      }\r
+\r
+    } else if (Status == EFI_DEVICE_ERROR) {\r
+      ReturnStatus = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+ConSplitterAbsolutePointerWaitForInput (\r
+  IN  EFI_EVENT                       Event,\r
+  IN  VOID                            *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This event agregates all the events of the pointer devices in the splitter.\r
+  If the ConIn is password locked then return.\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
+Arguments:\r
+  Event   - The Event assoicated with callback.\r
+  Context - Context registered when Event was created.\r
+\r
+Returns:\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  UINTN                         Index;\r
+\r
+  Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
+  if (Private->PasswordEnabled) {\r
+    //\r
+    // If StdIn Locked return not ready\r
+    //\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // if AbsoluteInputEventSignalState is flagged before,\r
+  // and not cleared by Reset() or GetState(), signal it\r
+  //\r
+  if (Private->AbsoluteInputEventSignalState) {\r
+    gBS->SignalEvent (Event);\r
+    return ;\r
+  }\r
+  //\r
+  // if any physical console input device has key input, signal the event.\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+    Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput);\r
+    if (!EFI_ERROR (Status)) {\r
+      gBS->SignalEvent (Event);\r
+      Private->AbsoluteInputEventSignalState = TRUE;\r
+    }\r
+  }\r
+}\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 ConSplitterTextOutReset (\r
@@ -3207,6 +4386,8 @@ ConSplitterTextOutQueryMode (
 --*/\r
 {\r
   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;\r
+  UINTN                           CurrentMode;\r
+  INT32                           *TextOutModeMap;\r
 \r
   Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
@@ -3222,8 +4403,18 @@ ConSplitterTextOutQueryMode (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  *Columns  = Private->TextOutQueryData[ModeNumber].Columns;\r
-  *Rows     = Private->TextOutQueryData[ModeNumber].Rows;\r
+  //\r
+  // We get the available mode from mode intersection map if it's available\r
+  //\r
+  if (Private->TextOutModeMap != NULL) {\r
+    TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
+    CurrentMode    = (UINTN)(*TextOutModeMap);\r
+    *Columns       = Private->TextOutQueryData[CurrentMode].Columns;\r
+    *Rows          = Private->TextOutQueryData[CurrentMode].Rows;\r
+  } else {\r
+    *Columns  = Private->TextOutQueryData[ModeNumber].Columns;\r
+    *Rows     = Private->TextOutQueryData[ModeNumber].Rows;\r
+  }\r
 \r
   if (*Columns <= 0 && *Rows <= 0) {\r
     return EFI_UNSUPPORTED;\r
@@ -3293,8 +4484,8 @@ ConSplitterTextOutSetMode (
                                                       TextOutModeMap[Index]\r
                                                       );\r
       //\r
-      // If this console device is based on a UGA device, then sync up the bitmap from\r
-      // the UGA splitter and reclear the text portion of the display in the new mode.\r
+      // If this console device is based on a GOP or UGA device, then sync up the bitmap from\r
+      // the GOP/UGA splitter and reclear the text portion of the display in the new mode.\r
       //\r
       if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
         Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
@@ -3460,11 +4651,26 @@ ConSplitterTextOutSetCursorPosition (
   EFI_STATUS                      ReturnStatus;\r
   UINTN                           MaxColumn;\r
   UINTN                           MaxRow;\r
+  INT32                           *TextOutModeMap;\r
+  INT32                           ModeNumber;\r
+  INT32                           CurrentMode;\r
 \r
   Private   = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+  TextOutModeMap  = NULL;\r
+  ModeNumber      = Private->TextOutMode.Mode;\r
 \r
-  MaxColumn = Private->TextOutQueryData[Private->TextOutMode.Mode].Columns;\r
-  MaxRow    = Private->TextOutQueryData[Private->TextOutMode.Mode].Rows;\r
+  //\r
+  // Get current MaxColumn and MaxRow from intersection map\r
+  //\r
+  if (Private->TextOutModeMap != NULL) {\r
+    TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
+    CurrentMode    = *TextOutModeMap;\r
+  } else {\r
+    CurrentMode = ModeNumber;\r
+  }\r
+\r
+  MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;\r
+  MaxRow    = Private->TextOutQueryData[CurrentMode].Rows;\r
 \r
   if (Column >= MaxColumn || Row >= MaxRow) {\r
     return EFI_UNSUPPORTED;\r
@@ -3543,3 +4749,4 @@ ConSplitterTextOutEnableCursor (
 \r
   return ReturnStatus;\r
 }\r
+\r