]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConPlatformDxe / ConPlatform.c
index f6483ed1fd0ec07767fc3b95bdf3971cd11d48fc..5fa7facfcac809393f9e7632a10d4e1723a89d60 100644 (file)
@@ -2,8 +2,8 @@
   Console Platform DXE Driver, install Console Device Guids and update Console\r
   Environment Variables.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -80,7 +80,7 @@ InitializeConPlatform(
 \r
 \r
 /**\r
-  Test to see if EFI_SIMPLE_TEXT_INPUT_PROTOCOL is supported on ControllerHandle. \r
+  Test to see if EFI_SIMPLE_TEXT_INPUT_PROTOCOL is supported on ControllerHandle.\r
 \r
   @param  This                Protocol instance pointer.\r
   @param  ControllerHandle    Handle of device to test.\r
@@ -108,7 +108,7 @@ ConPlatformTextInDriverBindingSupported (
 \r
 \r
 /**\r
-  Test to see if EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL is supported on ControllerHandle. \r
+  Test to see if EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL is supported on ControllerHandle.\r
 \r
   @param  This                Protocol instance pointer.\r
   @param  ControllerHandle    Handle of device to test.\r
@@ -136,7 +136,7 @@ ConPlatformTextOutDriverBindingSupported (
 \r
 \r
 /**\r
-  Test to see if the specified protocol is supported on ControllerHandle. \r
+  Test to see if the specified protocol is supported on ControllerHandle.\r
 \r
   @param  This                Protocol instance pointer.\r
   @param  ControllerHandle    Handle of device to test.\r
@@ -202,9 +202,9 @@ ConPlatformDriverBindingSupported (
   Start this driver on ControllerHandle by opening Simple Text Input Protocol,\r
   reading Device Path, and installing Console In Devcice GUID on ControllerHandle.\r
 \r
-  If this devcie is not one hot-plug devce, append its device path into the \r
+  If this devcie is not one hot-plug devce, append its device path into the\r
   console environment variables ConInDev.\r
-  \r
+\r
   @param  This                 Protocol instance pointer.\r
   @param  ControllerHandle     Handle of device to bind driver to\r
   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
@@ -226,6 +226,7 @@ ConPlatformTextInDriverBindingStart (
   EFI_STATUS                     Status;\r
   EFI_DEVICE_PATH_PROTOCOL       *DevicePath;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
+  BOOLEAN                        IsInConInVariable;\r
 \r
   //\r
   // Get the Device Path Protocol so the environment variables can be updated\r
@@ -255,6 +256,19 @@ ConPlatformTextInDriverBindingStart (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  //\r
+  // Check if the device path is in ConIn Variable\r
+  //\r
+  IsInConInVariable = FALSE;\r
+  Status = ConPlatformUpdateDeviceVariable (\r
+             L"ConIn",\r
+             DevicePath,\r
+             Check\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    IsInConInVariable = TRUE;\r
+  }\r
+\r
   //\r
   // Check the device path, if it is a hot plug device,\r
   // do not put the device path into ConInDev, and install\r
@@ -268,6 +282,16 @@ ConPlatformTextInDriverBindingStart (
            NULL,\r
            NULL\r
            );\r
+    //\r
+    // Append the device path to ConInDev only if it is in ConIn variable.\r
+    //\r
+    if (IsInConInVariable) {\r
+      ConPlatformUpdateDeviceVariable (\r
+        L"ConInDev",\r
+        DevicePath,\r
+        Append\r
+        );\r
+    }\r
   } else {\r
     //\r
     // If it is not a hot-plug device, append the device path to the\r
@@ -276,20 +300,14 @@ ConPlatformTextInDriverBindingStart (
     ConPlatformUpdateDeviceVariable (\r
       L"ConInDev",\r
       DevicePath,\r
-      APPEND\r
+      Append\r
       );\r
 \r
     //\r
-    // If the device path is successfully added to the ConIn environment variable,\r
+    // If the device path is an instance in the ConIn environment variable,\r
     // then install EfiConsoleInDeviceGuid onto ControllerHandle\r
     //\r
-    Status = ConPlatformUpdateDeviceVariable (\r
-               L"ConIn",\r
-               DevicePath,\r
-               CHECK\r
-               );\r
-\r
-    if (!EFI_ERROR (Status)) {\r
+    if (IsInConInVariable) {\r
       gBS->InstallMultipleProtocolInterfaces (\r
              &ControllerHandle,\r
              &gEfiConsoleInDeviceGuid,\r
@@ -310,15 +328,15 @@ ConPlatformTextInDriverBindingStart (
 }\r
 \r
 /**\r
-  Start this driver on the device for console output and stardard error output.\r
+  Start this driver on the device for console output and standard error output.\r
 \r
   Start this driver on ControllerHandle by opening Simple Text Output Protocol,\r
   reading Device Path, and installing Console Out Devcic GUID, Standard Error\r
   Device GUID on ControllerHandle.\r
 \r
-  If this devcie is not one hot-plug devce, append its device path into the \r
+  If this devcie is not one hot-plug devce, append its device path into the\r
   console environment variables ConOutDev, ErrOutDev.\r
-  \r
+\r
   @param  This                 Protocol instance pointer.\r
   @param  ControllerHandle     Handle of device to bind driver to\r
   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
@@ -341,6 +359,8 @@ ConPlatformTextOutDriverBindingStart (
   EFI_DEVICE_PATH_PROTOCOL         *DevicePath;\r
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
   BOOLEAN                          NeedClose;\r
+  BOOLEAN                          IsInConOutVariable;\r
+  BOOLEAN                          IsInErrOutVariable;\r
 \r
   NeedClose = TRUE;\r
 \r
@@ -372,6 +392,29 @@ ConPlatformTextOutDriverBindingStart (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  //\r
+  // Check if the device path is in ConOut & ErrOut Variable\r
+  //\r
+  IsInConOutVariable = FALSE;\r
+  Status = ConPlatformUpdateDeviceVariable (\r
+             L"ConOut",\r
+             DevicePath,\r
+             Check\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    IsInConOutVariable = TRUE;\r
+  }\r
+\r
+  IsInErrOutVariable = FALSE;\r
+  Status = ConPlatformUpdateDeviceVariable (\r
+             L"ErrOut",\r
+             DevicePath,\r
+             Check\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    IsInErrOutVariable = TRUE;\r
+  }\r
+\r
   //\r
   // Check the device path, if it is a hot plug device,\r
   // do not put the device path into ConOutDev and ErrOutDev,\r
@@ -385,36 +428,53 @@ ConPlatformTextOutDriverBindingStart (
            NULL,\r
            NULL\r
            );\r
-  } else {\r
     //\r
-    // If it is not a hot-plug device, first append the device path to the\r
-    // ConOutDev environment variable\r
+    // Append the device path to ConOutDev only if it is in ConOut variable.\r
     //\r
-    ConPlatformUpdateDeviceVariable (\r
-      L"ConOutDev",\r
-      DevicePath,\r
-      APPEND\r
-      );\r
+    if (IsInConOutVariable) {\r
+      ConPlatformUpdateDeviceVariable (\r
+        L"ConOutDev",\r
+        DevicePath,\r
+        Append\r
+        );\r
+    }\r
     //\r
-    // Then append the device path to the ErrOutDev environment variable\r
+    // Append the device path to ErrOutDev only if it is in ErrOut variable.\r
     //\r
-    ConPlatformUpdateDeviceVariable (\r
-      L"ErrOutDev",\r
-      DevicePath,\r
-      APPEND\r
-      );\r
+    if (IsInErrOutVariable) {\r
+      ConPlatformUpdateDeviceVariable (\r
+        L"ErrOutDev",\r
+        DevicePath,\r
+        Append\r
+        );\r
+    }\r
+  } else {\r
+    //\r
+    // If it is not a hot-plug device, append the device path to\r
+    // the ConOutDev and ErrOutDev environment variable.\r
+    // For GOP device path, append the sibling device path as well.\r
+    //\r
+    if (!ConPlatformUpdateGopCandidate (DevicePath)) {\r
+      ConPlatformUpdateDeviceVariable (\r
+        L"ConOutDev",\r
+        DevicePath,\r
+        Append\r
+        );\r
+      //\r
+      // Then append the device path to the ErrOutDev environment variable\r
+      //\r
+      ConPlatformUpdateDeviceVariable (\r
+        L"ErrOutDev",\r
+        DevicePath,\r
+        Append\r
+        );\r
+    }\r
 \r
     //\r
-    // If the device path is successfully added to the ConOut environment variable,\r
+    // If the device path is an instance in the ConOut environment variable,\r
     // then install EfiConsoleOutDeviceGuid onto ControllerHandle\r
     //\r
-    Status = ConPlatformUpdateDeviceVariable (\r
-               L"ConOut",\r
-               DevicePath,\r
-               CHECK\r
-               );\r
-\r
-    if (!EFI_ERROR (Status)) {\r
+    if (IsInConOutVariable) {\r
       NeedClose = FALSE;\r
       Status = gBS->InstallMultipleProtocolInterfaces (\r
                       &ControllerHandle,\r
@@ -424,15 +484,10 @@ ConPlatformTextOutDriverBindingStart (
                       );\r
     }\r
     //\r
-    // If the device path is successfully added to the ErrOut environment variable,\r
+    // If the device path is an instance in the ErrOut environment variable,\r
     // then install EfiStandardErrorDeviceGuid onto ControllerHandle\r
     //\r
-    Status = ConPlatformUpdateDeviceVariable (\r
-               L"ErrOut",\r
-               DevicePath,\r
-               CHECK\r
-               );\r
-    if (!EFI_ERROR (Status)) {\r
+    if (IsInErrOutVariable) {\r
       NeedClose = FALSE;\r
       gBS->InstallMultipleProtocolInterfaces (\r
              &ControllerHandle,\r
@@ -456,7 +511,7 @@ ConPlatformTextOutDriverBindingStart (
 }\r
 \r
 /**\r
-  Stop this driver on ControllerHandle by removing Console In Devcice GUID \r
+  Stop this driver on ControllerHandle by removing Console In Devcice GUID\r
   and closing the Simple Text Input protocol on ControllerHandle.\r
 \r
   @param  This              Protocol instance pointer.\r
@@ -492,22 +547,17 @@ ConPlatformTextInDriverBindingStop (
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
   //\r
-  // If it is not a hot-plug device, first delete it from the ConInDev variable.\r
+  // If there is device path on ControllerHandle\r
   //\r
-  if (!IsHotPlugDevice (DevicePath)) {\r
-   //\r
-    // Remove DevicePath from ConInDev\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Remove DevicePath from ConInDev if exists.\r
     //\r
     ConPlatformUpdateDeviceVariable (\r
       L"ConInDev",\r
       DevicePath,\r
-      DELETE\r
+      Delete\r
       );\r
   }\r
 \r
@@ -524,18 +574,18 @@ ConPlatformTextInDriverBindingStop (
   // Close the Simple Text Input Protocol\r
   //\r
   gBS->CloseProtocol (\r
-        ControllerHandle,\r
-        &gEfiSimpleTextInProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        ControllerHandle\r
-        );\r
+         ControllerHandle,\r
+         &gEfiSimpleTextInProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         ControllerHandle\r
+         );\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 \r
 /**\r
-  Stop this driver on ControllerHandle by removing Console Out Devcice GUID \r
+  Stop this driver on ControllerHandle by removing Console Out Devcice GUID\r
   and closing the Simple Text Output protocol on ControllerHandle.\r
 \r
   @param  This              Protocol instance pointer.\r
@@ -571,30 +621,22 @@ ConPlatformTextOutDriverBindingStop (
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // If it is not a hot-plug device, first delete it from the ConOutDev and ErrOutDev variable.\r
-  //\r
-  if (!IsHotPlugDevice (DevicePath)) {\r
+  if (!EFI_ERROR (Status)) {\r
     //\r
-    // Remove DevicePath from ConOutDev, and ErrOutDev\r
+    // Remove DevicePath from ConOutDev and ErrOutDev if exists.\r
     //\r
     ConPlatformUpdateDeviceVariable (\r
       L"ConOutDev",\r
       DevicePath,\r
-      DELETE\r
+      Delete\r
       );\r
     ConPlatformUpdateDeviceVariable (\r
       L"ErrOutDev",\r
       DevicePath,\r
-      DELETE\r
+      Delete\r
       );\r
   }\r
\r
+\r
   //\r
   // Uninstall the Console Device GUIDs from Controller Handle\r
   //\r
@@ -672,7 +714,7 @@ ConPlatformUnInstallProtocol (
   @param  Name             String part of EFI variable name\r
 \r
   @return Dynamically allocated memory that contains a copy of the EFI variable.\r
-          Caller is repsoncible freeing the buffer. Return NULL means Variable \r
+          Caller is repsoncible freeing the buffer. Return NULL means Variable\r
           was not read.\r
 \r
 **/\r
@@ -729,6 +771,57 @@ ConPlatformGetVariable (
   return Buffer;\r
 }\r
 \r
+/**\r
+  Function returns TRUE when the two input device paths point to the two\r
+  GOP child handles that have the same parent.\r
+\r
+  @param Left    A pointer to a device path data structure.\r
+  @param Right   A pointer to a device path data structure.\r
+\r
+  @retval TRUE  Left and Right share the same parent.\r
+  @retval FALSE Left and Right don't share the same parent or either of them is not\r
+                a GOP device path.\r
+**/\r
+BOOLEAN\r
+IsGopSibling (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *Left,\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *Right\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *NodeLeft;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NodeRight;\r
+\r
+  for (NodeLeft = Left; !IsDevicePathEndType (NodeLeft); NodeLeft = NextDevicePathNode (NodeLeft)) {\r
+    if ((DevicePathType (NodeLeft) == ACPI_DEVICE_PATH && DevicePathSubType (NodeLeft) == ACPI_ADR_DP) ||\r
+        (DevicePathType (NodeLeft) == HARDWARE_DEVICE_PATH && DevicePathSubType (NodeLeft) == HW_CONTROLLER_DP &&\r
+         DevicePathType (NextDevicePathNode (NodeLeft)) == ACPI_DEVICE_PATH && DevicePathSubType (NextDevicePathNode (NodeLeft)) == ACPI_ADR_DP)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (IsDevicePathEndType (NodeLeft)) {\r
+    return FALSE;\r
+  }\r
+\r
+  for (NodeRight = Right; !IsDevicePathEndType (NodeRight); NodeRight = NextDevicePathNode (NodeRight)) {\r
+    if ((DevicePathType (NodeRight) == ACPI_DEVICE_PATH && DevicePathSubType (NodeRight) == ACPI_ADR_DP) ||\r
+        (DevicePathType (NodeRight) == HARDWARE_DEVICE_PATH && DevicePathSubType (NodeRight) == HW_CONTROLLER_DP &&\r
+         DevicePathType (NextDevicePathNode (NodeRight)) == ACPI_DEVICE_PATH && DevicePathSubType (NextDevicePathNode (NodeRight)) == ACPI_ADR_DP)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (IsDevicePathEndType (NodeRight)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (((UINTN) NodeLeft - (UINTN) Left) != ((UINTN) NodeRight - (UINTN) Right)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return (BOOLEAN) (CompareMem (Left, Right, (UINTN) NodeLeft - (UINTN) Left) == 0);\r
+}\r
+\r
 /**\r
   Function compares a device path data structure to that of all the nodes of a\r
   second device path instance.\r
@@ -788,7 +881,7 @@ ConPlatformMatchDevicePaths (
   // Search for the match of 'Single' in 'Multi'\r
   //\r
   while (DevicePathInst != NULL) {\r
-    if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+    if ((CompareMem (Single, DevicePathInst, Size) == 0) || IsGopSibling (Single, DevicePathInst)) {\r
       if (!Delete) {\r
         //\r
         // If Delete is FALSE, return EFI_SUCCESS if Single is found in Multi.\r
@@ -829,7 +922,7 @@ ConPlatformMatchDevicePaths (
 }\r
 \r
 /**\r
-  Update console environment variables. \r
+  Update console environment variables.\r
 \r
   @param  VariableName    Console environment variables, ConOutDev, ConInDev\r
                           ErrOutDev, ConIn ,ConOut or ErrOut.\r
@@ -862,10 +955,10 @@ ConPlatformUpdateDeviceVariable (
   //\r
   VariableDevicePath = ConPlatformGetVariable (VariableName);\r
 \r
-  if (Operation != DELETE) {\r
+  if (Operation != Delete) {\r
     //\r
     // Match specified DevicePath in Console Variable.\r
-    // \r
+    //\r
     Status = ConPlatformMatchDevicePaths (\r
                VariableDevicePath,\r
                DevicePath,\r
@@ -873,7 +966,7 @@ ConPlatformUpdateDeviceVariable (
                FALSE\r
                );\r
 \r
-    if ((Operation == CHECK) || (!EFI_ERROR (Status))) {\r
+    if ((Operation == Check) || (!EFI_ERROR (Status))) {\r
       //\r
       // Branch here includes 2 cases:\r
       // 1. Operation is CHECK, simply return Status.\r
@@ -959,7 +1052,7 @@ IsHotPlugDevice (
   while (!IsDevicePathEnd (CheckDevicePath)) {\r
     //\r
     // Check device whether is hot plug device or not throught Device Path\r
-    // \r
+    //\r
     if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
         (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
          DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
@@ -976,9 +1069,52 @@ IsHotPlugDevice (
       //\r
       return TRUE;\r
     }\r
-  \r
+\r
     CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
   }\r
 \r
   return FALSE;\r
 }\r
+\r
+/**\r
+  Update ConOutDev and ErrOutDev variables to add the device path of\r
+  GOP controller itself and the sibling controllers.\r
+\r
+  @param  DevicePath            Pointer to device's device path.\r
+\r
+  @retval TRUE                  The devcie is a GOP device.\r
+  @retval FALSE                 The devcie is not a GOP device.\r
+\r
+**/\r
+BOOLEAN\r
+ConPlatformUpdateGopCandidate (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_HANDLE                           PciHandle;\r
+  EFI_HANDLE                           GopHandle;\r
+  EFI_DEVICE_PATH_PROTOCOL             *TempDevicePath;\r
+\r
+  //\r
+  // Check whether it's a GOP device.\r
+  //\r
+  TempDevicePath = DevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiGraphicsOutputProtocolGuid, &TempDevicePath, &GopHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  //\r
+  // Get the parent PciIo handle in order to find all the children\r
+  //\r
+  Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &DevicePath, &PciHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  TempDevicePath = EfiBootManagerGetGopDevicePath (PciHandle);\r
+  if (TempDevicePath != NULL) {\r
+    ConPlatformUpdateDeviceVariable (L"ConOutDev", TempDevicePath, Append);\r
+    ConPlatformUpdateDeviceVariable (L"ErrOutDev", TempDevicePath, Append);\r
+  }\r
+  return TRUE;\r
+}\r