]> 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 1c32a0c6ef765bb3a1a1593456365d4461ec4275..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,13 +154,24 @@ STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
     FALSE,\r
   },\r
   {\r
-    ConSpliterGraphicsOutputQueryMode,\r
-    ConSpliterGraphicsOutputSetMode,\r
-    ConSpliterGraphicsOutputBlt,\r
+    NULL,\r
+    NULL,\r
+    NULL\r
+  },\r
+  0,\r
+  0,\r
+  0,\r
+  0,\r
+  (EFI_UGA_PIXEL *) NULL,\r
+  {\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
@@ -158,13 +218,24 @@ STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
     FALSE,\r
   },\r
   {\r
-    ConSpliterGraphicsOutputQueryMode,\r
-    ConSpliterGraphicsOutputSetMode,\r
-    ConSpliterGraphicsOutputBlt,\r
+    NULL,\r
+    NULL,\r
+    NULL\r
+  },\r
+  0,\r
+  0,\r
+  0,\r
+  0,\r
+  (EFI_UGA_PIXEL *) NULL,\r
+  {\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
@@ -205,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
@@ -226,9 +309,9 @@ EFI_DRIVER_BINDING_PROTOCOL           gConSplitterStdErrDriverBinding = {
 /**\r
   The user Entry Point for module ConSplitter. The user code starts with this function.\r
 \r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
   @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
+\r
   @retval EFI_SUCCESS       The entry point is executed successfully.\r
   @retval other             Some error occurs when executing this entry point.\r
 \r
@@ -245,47 +328,53 @@ InitializeConSplitter(
   //\r
   // Install driver model protocol(s).\r
   //\r
-  Status = EfiLibInstallAllDriverProtocols (\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
              SystemTable,\r
              &gConSplitterConInDriverBinding,\r
              ImageHandle,\r
              &gConSplitterConInComponentName,\r
-             NULL,\r
-             NULL\r
+             &gConSplitterConInComponentName2\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = EfiLibInstallAllDriverProtocols (\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
              SystemTable,\r
              &gConSplitterSimplePointerDriverBinding,\r
              NULL,\r
              &gConSplitterSimplePointerComponentName,\r
+             &gConSplitterSimplePointerComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gConSplitterAbsolutePointerDriverBinding,\r
              NULL,\r
-             NULL\r
+             &gConSplitterAbsolutePointerComponentName,\r
+             &gConSplitterAbsolutePointerComponentName2\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = EfiLibInstallAllDriverProtocols (\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
              SystemTable,\r
              &gConSplitterConOutDriverBinding,\r
              NULL,\r
              &gConSplitterConOutComponentName,\r
-             NULL,\r
-             NULL\r
+             &gConSplitterConOutComponentName2\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = EfiLibInstallAllDriverProtocols (\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
              SystemTable,\r
              &gConSplitterStdErrDriverBinding,\r
              NULL,\r
              &gConSplitterStdErrComponentName,\r
-             NULL,\r
-             NULL\r
+             &gConSplitterStdErrComponentName2\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -321,6 +410,8 @@ Returns:
 {\r
   EFI_STATUS  Status;\r
 \r
+  ASSERT (FeaturePcdGet (PcdConOutGopSupport) ||\r
+          FeaturePcdGet (PcdConOutUgaSupport));\r
   //\r
   // The driver creates virtual handles for ConIn, ConOut, and StdErr.\r
   // The virtual handles will always exist even if no console exist in the\r
@@ -349,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
@@ -368,21 +463,58 @@ Returns:
   //\r
   Status = ConSplitterTextOutConstructor (&mConOut);\r
   if (!EFI_ERROR (Status)) {\r
-    //\r
-    // In UEFI mode, Graphics Output Protocol is installed on virtual handle.\r
-    //\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                    &mConOut.VirtualHandle,\r
-                    &gEfiSimpleTextOutProtocolGuid,\r
-                    &mConOut.TextOut,\r
-                    &gEfiGraphicsOutputProtocolGuid,\r
-                    &mConOut.GraphicsOutput,\r
-                    &gEfiConsoleControlProtocolGuid,\r
-                    &mConOut.ConsoleControl,\r
-                    &gEfiPrimaryConsoleOutDeviceGuid,\r
-                    NULL,\r
-                    NULL\r
-                    );\r
+    if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
+      //\r
+      // In EFI mode, UGA Draw protocol is installed\r
+      //\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &mConOut.VirtualHandle,\r
+                      &gEfiSimpleTextOutProtocolGuid,\r
+                      &mConOut.TextOut,\r
+                      &gEfiUgaDrawProtocolGuid,\r
+                      &mConOut.UgaDraw,\r
+                      &gEfiConsoleControlProtocolGuid,\r
+                      &mConOut.ConsoleControl,\r
+                      &gEfiPrimaryConsoleOutDeviceGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+    } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
+      //\r
+      // In UEFI mode, Graphics Output Protocol is installed on virtual handle.\r
+      //\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &mConOut.VirtualHandle,\r
+                      &gEfiSimpleTextOutProtocolGuid,\r
+                      &mConOut.TextOut,\r
+                      &gEfiGraphicsOutputProtocolGuid,\r
+                      &mConOut.GraphicsOutput,\r
+                      &gEfiConsoleControlProtocolGuid,\r
+                      &mConOut.ConsoleControl,\r
+                      &gEfiPrimaryConsoleOutDeviceGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+    } else {\r
+      //\r
+      // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are\r
+      // installed on virtual handle.\r
+      //\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &mConOut.VirtualHandle,\r
+                      &gEfiSimpleTextOutProtocolGuid,\r
+                      &mConOut.TextOut,\r
+                      &gEfiGraphicsOutputProtocolGuid,\r
+                      &mConOut.GraphicsOutput,\r
+                      &gEfiUgaDrawProtocolGuid,\r
+                      &mConOut.UgaDraw,\r
+                      &gEfiConsoleControlProtocolGuid,\r
+                      &mConOut.ConsoleControl,\r
+                      &gEfiPrimaryConsoleOutDeviceGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+    }\r
 \r
     if (!EFI_ERROR (Status)) {\r
       //\r
@@ -459,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
@@ -487,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
@@ -517,41 +707,52 @@ ConSplitterTextOutConstructor (
   ConOutPrivate->TextOutQueryData[0].Rows     = 25;\r
   DevNullTextOutSetMode (ConOutPrivate, 0);\r
 \r
-  //\r
-  // Setup resource for mode information in Graphics Output Protocol interface\r
-  //\r
-  if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  //\r
-  // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel\r
-  //\r
-  if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+    //\r
+    // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel\r
+    //\r
+    ConSpliterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60);\r
   }\r
-  ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800;\r
-  ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600;\r
+  if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+    //\r
+    // Setup resource for mode information in Graphics Output Protocol interface\r
+    //\r
+    if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\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 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\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
-  //\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
+    // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()\r
+    // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
+    //\r
+    ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
+    ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;\r
 \r
-  ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
-  //\r
-  // Initial current mode to unknow state, and then set to mode 0\r
-  //\r
-  ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;\r
-  ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);\r
+    ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
+    //\r
+    // Initial current mode to unknow state, and then set to mode 0\r
+    //\r
+    ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;\r
+    ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -683,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
@@ -835,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
@@ -852,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
@@ -897,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
@@ -971,6 +1265,20 @@ Returns:
   Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);\r
   ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
 \r
+  if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+    //\r
+    // Match the UGA mode data of ConOut with the current mode\r
+    //\r
+    if (UgaDraw != NULL) {\r
+      UgaDraw->GetMode (\r
+                 UgaDraw,\r
+                 &mConOut.UgaHorizontalResolution,\r
+                 &mConOut.UgaVerticalResolution,\r
+                 &mConOut.UgaColorDepth,\r
+                 &mConOut.UgaRefreshRate\r
+                 );\r
+    }\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -1118,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
@@ -1186,7 +1513,7 @@ Returns:
 \r
 EFI_STATUS\r
 EFIAPI\r
-ConSplitterConOutDriverBindingStop (\r
+ConSplitterAbsolutePointerDriverBindingStop (\r
   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
   IN  EFI_HANDLE                      ControllerHandle,\r
   IN  UINTN                           NumberOfChildren,\r
@@ -1205,34 +1532,33 @@ Returns:
 \r
 --*/\r
 {\r
-  EFI_STATUS                       Status;\r
-  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\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
-            mConOut.VirtualHandle,\r
-            &gEfiConsoleOutDeviceGuid,\r
-            &gEfiSimpleTextOutProtocolGuid,\r
-            (VOID **) &TextOut\r
-            );\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
   //\r
-  // Delete this console output device's data structures.\r
+  // Delete this console input device's data structures.\r
   //\r
-  return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);\r
+  return ConSplitterAbsolutePointerDeleteDevice (&mConIn, AbsolutePointer);\r
 }\r
 \r
 EFI_STATUS\r
 EFIAPI\r
-ConSplitterStdErrDriverBindingStop (\r
+ConSplitterConOutDriverBindingStop (\r
   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
   IN  EFI_HANDLE                      ControllerHandle,\r
   IN  UINTN                           NumberOfChildren,\r
@@ -1247,7 +1573,7 @@ Arguments:
 \r
 Returns:\r
 \r
-  EFI_SUCCESS - Complete successfully.\r
+  None\r
 \r
 --*/\r
 {\r
@@ -1261,22 +1587,68 @@ Returns:
   Status = ConSplitterStop (\r
             This,\r
             ControllerHandle,\r
-            mStdErr.VirtualHandle,\r
-            &gEfiStandardErrorDeviceGuid,\r
+            mConOut.VirtualHandle,\r
+            &gEfiConsoleOutDeviceGuid,\r
             &gEfiSimpleTextOutProtocolGuid,\r
             (VOID **) &TextOut\r
             );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   //\r
-  // Delete this console error out device's data structures.\r
+  // Delete this console output device's data structures.\r
   //\r
-  Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
+  return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterStdErrDriverBindingStop (\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
+  EFI_SUCCESS - Complete successfully.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = ConSplitterStop (\r
+            This,\r
+            ControllerHandle,\r
+            mStdErr.VirtualHandle,\r
+            &gEfiStandardErrorDeviceGuid,\r
+            &gEfiSimpleTextOutProtocolGuid,\r
+            (VOID **) &TextOut\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Delete this console error out device's data structures.\r
+  //\r
+  Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   if (mStdErr.CurrentNumberOfConsoles == 0) {\r
     gST->StandardErrorHandle  = NULL;\r
     gST->StdErr               = NULL;\r
@@ -1435,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
@@ -1512,6 +1944,83 @@ Returns:
   return EFI_NOT_FOUND;\r
 }\r
 \r
+EFI_STATUS\r
+ConSplitterAbsolutePointerAddDevice (\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
+  EFI_OUT_OF_RESOURCES\r
+  EFI_SUCCESS\r
+\r
+--*/\r
+{\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
@@ -1734,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
@@ -1754,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
@@ -1799,7 +2311,7 @@ Arguments:
 \r
 Returns:\r
 \r
-  None\r
+  EFI_SUCCESS\r
   EFI_OUT_OF_RESOURCES\r
 \r
 --*/\r
@@ -1810,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
@@ -1822,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
@@ -1857,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
@@ -1889,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
@@ -1961,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
@@ -1976,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
@@ -1991,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
@@ -2007,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
@@ -2016,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
@@ -2032,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
@@ -2041,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
@@ -2057,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
@@ -2066,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
@@ -2103,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
@@ -2119,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
@@ -2149,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
@@ -2183,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
@@ -2215,20 +2813,61 @@ Returns:
   MaxMode     = Private->TextOutMode.MaxMode;\r
   ASSERT (MaxMode >= 1);\r
 \r
-  if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
-    ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\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
-    DevNullGopSync (Private, GraphicsOutput, UgaDraw);\r
+    if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+      DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
+    } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+      DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
+    }\r
   } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {\r
     //\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
@@ -2272,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
@@ -2677,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
@@ -2704,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
@@ -2741,8 +3434,385 @@ 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 keystroke information was not returned due to\r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.\r
+\r
+--*/\r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  EFI_KEY_DATA                  CurrentKeyData;\r
+\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
+  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
+      CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_READY;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\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
+    Set certain state for the input device.\r
+\r
+  Arguments:\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 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
+  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
@@ -2902,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
@@ -3124,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
@@ -3139,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
@@ -3210,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
@@ -3377,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
@@ -3460,3 +4749,4 @@ ConSplitterTextOutEnableCursor (
 \r
   return ReturnStatus;\r
 }\r
+\r