]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
add PCD PcdUgaConsumeSupport to switch on/off EFI UGA Draw Protocol's consuming,...
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitter.c
index 63be0b1d8b467a139545e0a3db3a7f531611f387..00c809b6aae4d1cc9afef026ec8bd8f2328469be 100644 (file)
@@ -683,6 +683,12 @@ ConSplitterTextOutConstructor (
   //\r
   ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;\r
 \r
+  //\r
+  // When new console device is added, the new mode will be set later,\r
+  // so put current mode back to init state.\r
+  //\r
+  ConOutPrivate->TextOutMode.Mode = 0xFF;\r
+\r
   Status = ConSplitterGrowBuffer (\r
             sizeof (TEXT_OUT_AND_GOP_DATA),\r
             &ConOutPrivate->TextOutListCount,\r
@@ -1230,6 +1236,9 @@ Returns:
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
+  GraphicsOutput = NULL;\r
+  UgaDraw        = NULL;\r
   //\r
   // Try to Open Graphics Output protocol\r
   //\r
@@ -1241,23 +1250,27 @@ Returns:
                   mConOut.VirtualHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
-  if (EFI_ERROR (Status)) {\r
-    GraphicsOutput = NULL;\r
+\r
+  if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+    //\r
+    // Open UGA_DRAW protocol\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    ControllerHandle,\r
+                    &gEfiUgaDrawProtocolGuid,\r
+                    (VOID **) &UgaDraw,\r
+                    This->DriverBindingHandle,\r
+                    mConOut.VirtualHandle,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
   }\r
+\r
   //\r
-  // Open UGA_DRAW protocol\r
+  // When new console device is added, the new mode will be set later,\r
+  // so put current mode back to init state.\r
   //\r
-  Status = gBS->OpenProtocol (\r
-                  ControllerHandle,\r
-                  &gEfiUgaDrawProtocolGuid,\r
-                  (VOID **) &UgaDraw,\r
-                  This->DriverBindingHandle,\r
-                  mConOut.VirtualHandle,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    UgaDraw = NULL;\r
-  }\r
+  mConOut.TextOutMode.Mode = 0xFF;\r
+\r
   //\r
   // If both ConOut and StdErr incorporate the same Text Out device,\r
   // their MaxMode and QueryData should be the intersection of both.\r
@@ -1265,7 +1278,7 @@ Returns:
   Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);\r
   ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
 \r
-  if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+  if (FeaturePcdGet (PcdConOutUgaSupport) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
     //\r
     // Match the UGA mode data of ConOut with the current mode\r
     //\r
@@ -1319,6 +1332,13 @@ Returns:
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
+  //\r
+  // When new console device is added, the new mode will be set later,\r
+  // so put current mode back to init state.\r
+  //\r
+  mStdErr.TextOutMode.Mode = 0xFF;\r
+\r
   //\r
   // If both ConOut and StdErr incorporate the same Text Out device,\r
   // their MaxMode and QueryData should be the intersection of both.\r
@@ -2152,12 +2172,20 @@ Returns:
   Mode  = 0;\r
   Index = 0;\r
   while (Mode < MaxMode) {\r
-    TextOut->QueryMode (\r
-              TextOut,\r
-              Mode,\r
-              &Private->TextOutQueryData[Mode].Columns,\r
-              &Private->TextOutQueryData[Mode].Rows\r
-              );\r
+    Status = TextOut->QueryMode (\r
+                  TextOut,\r
+                  Mode,\r
+                  &Private->TextOutQueryData[Mode].Columns,\r
+                  &Private->TextOutQueryData[Mode].Rows\r
+                  );\r
+    //\r
+    // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData\r
+    // is clear to 0x0.\r
+    //\r
+    if ((EFI_ERROR(Status)) && (Mode == 1)) {\r
+      Private->TextOutQueryData[Mode].Columns = 0;\r
+      Private->TextOutQueryData[Mode].Rows = 0;\r
+    }\r
     Private->TextOutModeMap[Index] = Mode;\r
     Mode++;\r
     Index += Private->TextOutListCount;\r
@@ -2166,6 +2194,24 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Reconstruct TextOutModeMap to get intersection of modes\r
+\r
+  This routine reconstruct TextOutModeMap to get the intersection\r
+  of modes for all console out devices. Because EFI/UEFI spec require\r
+  mode 0 is 80x25, mode 1 is 80x50, this routine will not check the\r
+  intersection for mode 0 and mode 1.\r
+\r
+  @parm TextOutModeMap  Current text out mode map, begin with the mode 80x25\r
+  @parm NewlyAddedMap   New text out mode map, begin with the mode 80x25\r
+  @parm MapStepSize     Mode step size for one console device\r
+  @parm NewMapStepSize  Mode step size for one console device\r
+  @parm MaxMode         Current max text mode\r
+  @parm CurrentMode     Current text mode\r
+\r
+  @retval None\r
+\r
+**/\r
 STATIC\r
 VOID\r
 ConSplitterGetIntersection (\r
@@ -2183,9 +2229,16 @@ ConSplitterGetIntersection (
   INT32 CurrentMaxMode;\r
   INT32 Mode;\r
 \r
-  Index           = 0;\r
-  CurrentMapEntry = TextOutModeMap;\r
-  NextMapEntry    = TextOutModeMap;\r
+  //\r
+  // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved\r
+  // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection\r
+  // for mode 0 and mode 1, mode number starts from 2.\r
+  //\r
+  Index           = 2;\r
+  CurrentMapEntry = &TextOutModeMap[MapStepSize * 2];\r
+  NextMapEntry    = &TextOutModeMap[MapStepSize * 2];\r
+  NewlyAddedMap   = &NewlyAddedMap[NewMapStepSize * 2];\r
+\r
   CurrentMaxMode  = *MaxMode;\r
   Mode            = *CurrentMode;\r
 \r
@@ -2248,6 +2301,7 @@ Returns:
   UINTN                         Rows;\r
   UINTN                         Columns;\r
   UINTN                         StepSize;\r
+  EFI_STATUS                    Status;\r
 \r
   //\r
   // Must make sure that current mode won't change even if mode number changes\r
@@ -2263,9 +2317,16 @@ Returns:
   Mode      = 0;\r
   MapTable  = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
   while (Mode < TextOut->Mode->MaxMode) {\r
-    TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
+    Status = TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
+    if (EFI_ERROR(Status)) {\r
+      if (Mode == 1) {\r
         MapTable[StepSize] = Mode;\r
-\r
+        TextOutQueryData[Mode].Columns = 0;\r
+        TextOutQueryData[Mode].Rows = 0;\r
+      }\r
+      Mode++;\r
+      continue;\r
+    }\r
     //\r
     // Search the intersection map and QueryData database to see if they intersects\r
     //\r
@@ -2650,7 +2711,7 @@ Returns:
       }\r
     }\r
   }\r
-  if (UgaDraw != NULL) {\r
+  if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
     //\r
     // Graphics console driver can ensure the same mode for all GOP devices\r
     // so we can get the current mode from this video device\r
@@ -2690,7 +2751,7 @@ Done:
   if (GraphicsOutput != NULL) {\r
     Private->CurrentNumberOfGraphicsOutput++;\r
   }\r
-  if (UgaDraw != NULL) {\r
+  if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
     Private->CurrentNumberOfUgaDraw++;\r
   }\r
 \r
@@ -2720,6 +2781,112 @@ Done:
   return Status;\r
 }\r
 \r
+VOID\r
+ConsplitterSetConsoleOutMode (\r
+  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine will get the current console mode information (column, row)\r
+  from ConsoleOutMode variable and set it; if the variable does not exist,\r
+  set to user defined console mode.\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN                         Col;\r
+  UINTN                         Row;\r
+  UINTN                         Mode;\r
+  UINTN                         PreferMode;\r
+  UINTN                         BaseMode;\r
+  UINTN                         ModeInfoSize;\r
+  UINTN                         MaxMode;\r
+  EFI_STATUS                    Status;\r
+  CONSOLE_OUT_MODE              *ModeInfo;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
+\r
+  PreferMode   = 0xFF;\r
+  BaseMode     = 0xFF;\r
+  TextOut      = &Private->TextOut;\r
+  MaxMode      = (UINTN) (TextOut->Mode->MaxMode);\r
+  ModeInfoSize = sizeof (CONSOLE_OUT_MODE);\r
+\r
+  ModeInfo = AllocateZeroPool (sizeof(CONSOLE_OUT_MODE));\r
+  ASSERT(ModeInfo != NULL);\r
+\r
+  Status = gRT->GetVariable (\r
+                   VarConOutMode,\r
+                   &gEfiGenericPlatformVariableGuid,\r
+                   NULL,\r
+                   &ModeInfoSize,\r
+                   ModeInfo\r
+                   );\r
+\r
+  //\r
+  // Set to the default mode 80 x 25 required by EFI/UEFI spec;\r
+  // user can also define other valid default console mode here.\r
+  //\r
+  if (EFI_ERROR(Status)) {\r
+    ModeInfo->Column = 80;\r
+    ModeInfo->Row    = 25;\r
+    Status = gRT->SetVariable (\r
+                    VarConOutMode,\r
+                    &gEfiGenericPlatformVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                    sizeof (CONSOLE_OUT_MODE),\r
+                    ModeInfo\r
+                    );\r
+  }\r
+\r
+  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
+      }\r
+      if (Col == 80 && Row == 25) {\r
+        BaseMode = Mode;\r
+      }\r
+    }\r
+  }\r
+\r
+  Status = TextOut->SetMode (TextOut, PreferMode);\r
+\r
+  //\r
+  // if current mode setting is failed, default 80x25 mode will be set.\r
+  //\r
+  if (EFI_ERROR(Status)) {\r
+    Status = TextOut->SetMode (TextOut, BaseMode);\r
+    ASSERT(!EFI_ERROR(Status));\r
+\r
+    ModeInfo->Column = 80;\r
+    ModeInfo->Row    = 25;\r
+\r
+    //\r
+    // Update ConOutMode variable\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    VarConOutMode,\r
+                    &gEfiGenericPlatformVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                    sizeof (CONSOLE_OUT_MODE),\r
+                    ModeInfo\r
+                    );\r
+  }\r
+\r
+  gBS->FreePool (ModeInfo);\r
+}\r
+\r
+\r
 EFI_STATUS\r
 ConSplitterTextOutAddDevice (\r
   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA     *Private,\r
@@ -2822,7 +2989,7 @@ Returns:
     }\r
   }\r
   if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
-    if (UgaDraw != NULL) {\r
+    if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
       Status = UgaDraw->GetMode (\r
                     UgaDraw,\r
                     &UgaHorizontalResolution,\r
@@ -2875,6 +3042,12 @@ Returns:
     Private->TextOut.SetMode (&Private->TextOut, 0);\r
   }\r
 \r
+  //\r
+  // After adding new console device, all existing console devices should be\r
+  // synced to the current shared mode.\r
+  //\r
+  ConsplitterSetConsoleOutMode (Private);\r
+\r
   return Status;\r
 }\r
 \r
@@ -2911,7 +3084,7 @@ 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
+      if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
         Private->CurrentNumberOfUgaDraw--;\r
       }\r
       if (TextOutList->GraphicsOutput != NULL) {\r