]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
Keep StdErr same logic initialization with ConOut, e.g. initialize gST->StandardError...
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitter.c
index 57704d878eaf2a028779ff3015e78e468fbdb522..ab42b924dd55f8a163d9ca0fafe1f9c131a4362b 100644 (file)
@@ -16,7 +16,7 @@
   never removed. Such design ensures sytem function well during none console\r
   device situation.\r
 \r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -169,7 +169,6 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
   (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
   0,\r
   0,\r
-  TRUE,\r
 \r
   0,\r
   (TEXT_OUT_AND_GOP_DATA *) NULL,\r
@@ -225,7 +224,6 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
   (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
   0,\r
   0,\r
-  TRUE,\r
 \r
   0,\r
   (TEXT_OUT_AND_GOP_DATA *) NULL,\r
@@ -379,7 +377,7 @@ ConSplitterDriverEntry(
           FeaturePcdGet (PcdConOutUgaSupport));\r
 \r
   //\r
-  // The driver creates virtual handles for ConIn, ConOut.\r
+  // The driver creates virtual handles for ConIn, ConOut, StdErr.\r
   // The virtual handles will always exist even if no console exist in the\r
   // system. This is need to support hotplug devices like USB.\r
   //\r
@@ -467,6 +465,28 @@ ConSplitterDriverEntry(
     }\r
 \r
   }\r
+\r
+  //\r
+  // Create virtual device handle for StdErr Splitter\r
+  //\r
+  Status = ConSplitterTextOutConstructor (&mStdErr);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &mStdErr.VirtualHandle,\r
+                    &gEfiSimpleTextOutProtocolGuid,\r
+                    &mStdErr.TextOut,\r
+                    NULL\r
+                    );\r
+    if (!EFI_ERROR (Status)) {  \r
+      //\r
+      // Update the EFI System Table with new virtual console\r
+      // and update the pointer to Text Output protocol.\r
+      //\r
+      gST->StandardErrorHandle  = mStdErr.VirtualHandle;\r
+      gST->StdErr               = &mStdErr.TextOut;\r
+    }\r
+  }\r
+  \r
   //\r
   // Update the CRC32 in the EFI System Table header\r
   //\r
@@ -1315,27 +1335,6 @@ ConSplitterStdErrDriverBindingStart (
   EFI_STATUS                       Status;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
 \r
-  if (mStdErr.CurrentNumberOfConsoles == 0) {\r
-    //\r
-    // Construct console output devices' private data\r
-    //\r
-    Status = ConSplitterTextOutConstructor (&mStdErr);\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Create virtual device handle for StdErr Splitter\r
-      //\r
-      Status = gBS->InstallMultipleProtocolInterfaces (\r
-                      &mStdErr.VirtualHandle,\r
-                      &gEfiSimpleTextOutProtocolGuid,\r
-                      &mStdErr.TextOut,\r
-                      NULL\r
-                      );\r
-    }\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-\r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
   // agrogated console device on first call Start for a StandardError handle.\r
@@ -1368,20 +1367,6 @@ ConSplitterStdErrDriverBindingStart (
     return Status;\r
   }\r
 \r
-  if (mStdErr.CurrentNumberOfConsoles == 1) {\r
-    gST->StandardErrorHandle  = mStdErr.VirtualHandle;\r
-    gST->StdErr               = &mStdErr.TextOut;\r
-    //\r
-    // Update the CRC32 in the EFI System Table header\r
-    //\r
-    gST->Hdr.CRC32 = 0;\r
-    gBS->CalculateCrc32 (\r
-          (UINT8 *) &gST->Hdr,\r
-          gST->Hdr.HeaderSize,\r
-          &gST->Hdr.CRC32\r
-          );\r
-  }\r
-\r
   return Status;\r
 }\r
 \r
@@ -1718,38 +1703,7 @@ ConSplitterStdErrDriverBindingStop (
   //\r
   // Delete this console error out device's data structures.\r
   //\r
-  Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (mStdErr.CurrentNumberOfConsoles == 0) {\r
-    mStdErr.VirtualHandle     = NULL;\r
-\r
-    gST->StandardErrorHandle  = NULL;\r
-    gST->StdErr               = NULL;\r
-    //\r
-    // Update the CRC32 in the EFI System Table header\r
-    //\r
-    gST->Hdr.CRC32 = 0;\r
-    gBS->CalculateCrc32 (\r
-          (UINT8 *) &gST->Hdr,\r
-          gST->Hdr.HeaderSize,\r
-          &gST->Hdr.CRC32\r
-          );\r
-\r
-    //\r
-    // Uninstall Simple Text Output protocol from StdErr Handle.\r
-    //\r
-    gBS->UninstallMultipleProtocolInterfaces (\r
-           mStdErr.VirtualHandle,\r
-           &gEfiSimpleTextOutProtocolGuid,\r
-           &mStdErr.TextOut,\r
-           NULL\r
-           );\r
-  }\r
-\r
-  return Status;\r
+  return ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
 }\r
 \r
 \r
@@ -2832,9 +2786,7 @@ Done:
 \r
   //\r
   // Force GraphicsOutput mode to be set,\r
-  // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
   //\r
-  Private->HardwareNeedsStarting = TRUE;\r
   \r
   Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];\r
   if ((GraphicsOutput != NULL) &&\r
@@ -2905,6 +2857,7 @@ ConsplitterSetConsoleOutMode (
   UINTN                            MaxMode;\r
   EFI_STATUS                       Status;\r
   CONSOLE_OUT_MODE                 ModeInfo;\r
+  CONSOLE_OUT_MODE                 MaxModeInfo;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
 \r
   PreferMode   = 0xFF;\r
@@ -2912,8 +2865,10 @@ ConsplitterSetConsoleOutMode (
   TextOut      = &Private->TextOut;\r
   MaxMode      = (UINTN) (TextOut->Mode->MaxMode);\r
 \r
-  ModeInfo.Column = PcdGet32 (PcdConOutColumn);\r
-  ModeInfo.Row    = PcdGet32 (PcdConOutRow);\r
+  MaxModeInfo.Column = 0;\r
+  MaxModeInfo.Row    = 0; \r
+  ModeInfo.Column    = PcdGet32 (PcdConOutColumn);\r
+  ModeInfo.Row       = PcdGet32 (PcdConOutRow);\r
 \r
   //\r
   // To find the prefer mode and basic mode from Text Out mode list\r
@@ -2921,8 +2876,23 @@ ConsplitterSetConsoleOutMode (
   for (Mode = 0; Mode < MaxMode; Mode++) {\r
     Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);\r
     if (!EFI_ERROR(Status)) {\r
-      if (Col == ModeInfo.Column && Row == ModeInfo.Row) {\r
-        PreferMode = Mode;\r
+      if ((ModeInfo.Column != 0) && (ModeInfo.Row != 0)) {\r
+        //\r
+        // Use user defined column and row\r
+        //\r
+        if (Col == ModeInfo.Column && Row == ModeInfo.Row) {\r
+          PreferMode = Mode;\r
+        }\r
+      } else {\r
+        //\r
+        // If user sets PcdConOutColumn or PcdConOutRow to 0,\r
+        // find and set the highest text mode.\r
+        //\r
+        if ((Col >= MaxModeInfo.Column) && (Row >= MaxModeInfo.Row)) {\r
+          MaxModeInfo.Column  = Col;\r
+          MaxModeInfo.Row     = Row;\r
+          PreferMode          = Mode;\r
+        }\r
       }\r
       if (Col == 80 && Row == 25) {\r
         BaseMode = Mode;\r
@@ -4189,37 +4159,21 @@ ConSplitterTextOutOutputString (
   EFI_STATUS                      Status;\r
   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;\r
   UINTN                           Index;\r
-  UINTN                           BackSpaceCount;\r
   EFI_STATUS                      ReturnStatus;\r
-  CHAR16                          *TargetString;\r
+  UINTN                           MaxColumn;\r
+  UINTN                           MaxRow;\r
 \r
   This->SetAttribute (This, This->Mode->Attribute);\r
 \r
   Private         = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
-  BackSpaceCount  = 0;\r
-\r
-  for (TargetString = WString; *TargetString != L'\0'; TargetString++) {\r
-    if (*TargetString == CHAR_BACKSPACE) {\r
-      BackSpaceCount++;\r
-    }\r
-  }\r
-\r
-  if (BackSpaceCount == 0) {\r
-    TargetString = WString;\r
-  } else {\r
-    TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));\r
-    ASSERT (TargetString != NULL);\r
-\r
-    StrCpy (TargetString, WString);\r
-  }\r
   //\r
   // return the worst status met\r
   //\r
   for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
     Status = Private->TextOutList[Index].TextOut->OutputString (\r
                                                     Private->TextOutList[Index].TextOut,\r
-                                                    TargetString\r
+                                                    WString\r
                                                     );\r
     if (EFI_ERROR (Status)) {\r
       ReturnStatus = Status;\r
@@ -4229,10 +4183,50 @@ ConSplitterTextOutOutputString (
   if (Private->CurrentNumberOfConsoles > 0) {\r
     Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn;\r
     Private->TextOutMode.CursorRow    = Private->TextOutList[0].TextOut->Mode->CursorRow;\r
-  }\r
-\r
-  if (BackSpaceCount > 0) {\r
-    FreePool (TargetString);\r
+  } else {\r
+    //\r
+    // When there is no real console devices in system, \r
+    // update cursor position for the virtual device in consplitter.\r
+    //\r
+    Private->TextOut.QueryMode (\r
+                       &Private->TextOut,\r
+                       Private->TextOutMode.Mode,\r
+                       &MaxColumn,\r
+                       &MaxRow\r
+                       );    \r
+    for (; *WString != CHAR_NULL; WString++) {\r
+      switch (*WString) {\r
+      case CHAR_BACKSPACE:\r
+        if (Private->TextOutMode.CursorColumn == 0 && Private->TextOutMode.CursorRow > 0) {\r
+          Private->TextOutMode.CursorRow--;\r
+          Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1);          \r
+        } else if (Private->TextOutMode.CursorColumn > 0) {\r
+          Private->TextOutMode.CursorColumn--;\r
+        }\r
+        break;\r
+      \r
+      case CHAR_LINEFEED:\r
+        if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
+          Private->TextOutMode.CursorRow++;\r
+        }\r
+        break;\r
+      \r
+      case CHAR_CARRIAGE_RETURN:\r
+        Private->TextOutMode.CursorColumn = 0;\r
+        break;\r
+      \r
+      default:\r
+        if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {\r
+          Private->TextOutMode.CursorColumn++;\r
+        } else {\r
+          Private->TextOutMode.CursorColumn = 0;\r
+          if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
+            Private->TextOutMode.CursorRow++;\r
+          }\r
+        }\r
+        break;\r
+      }\r
+    }\r
   }\r
 \r
   return ReturnStatus;\r