]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c
Update ConPlatform driver to support GOP driver which creates multiple children.
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConPlatformDxe / ConPlatform.c
index bc5216dd82ee1aa6152d4c4ffe8949c0e5854950..0644ee38b9397986730c5cea23301d42b1d5a255 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 - 2010, 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
@@ -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
@@ -256,18 +257,41 @@ ConPlatformTextInDriverBindingStart (
     return Status;\r
   }\r
   //\r
-  // Check the device handle, if it is a hot plug device,\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
   // gEfiConsoleInDeviceGuid to the device handle directly.\r
   // The policy is, make hot plug device plug in and play immediately.\r
   //\r
-  if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
+  if (IsHotPlugDevice (DevicePath)) {\r
     gBS->InstallMultipleProtocolInterfaces (\r
            &ControllerHandle,\r
            &gEfiConsoleInDeviceGuid,\r
            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 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
@@ -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
@@ -373,48 +393,88 @@ ConPlatformTextOutDriverBindingStart (
     return Status;\r
   }\r
   //\r
-  // Check the device handle, if it is a hot plug device,\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
   // and install gEfiConsoleOutDeviceGuid to the device handle directly.\r
   // The policy is, make hot plug device plug in and play immediately.\r
   //\r
-  if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
+  if (IsHotPlugDevice (DevicePath)) {\r
     gBS->InstallMultipleProtocolInterfaces (\r
            &ControllerHandle,\r
            &gEfiConsoleOutDeviceGuid,\r
            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 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
@@ -427,12 +487,7 @@ ConPlatformTextOutDriverBindingStart (
     // 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
@@ -482,31 +537,30 @@ ConPlatformTextInDriverBindingStop (
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
 \r
   //\r
-  // If it is not a hot-plug device, first delete it from the ConInDev variable.\r
+  // Get the Device Path Protocol firstly\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &DevicePath,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  //\r
+  // If there is device path on ControllerHandle\r
   //\r
-  if (!IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
+  if (!EFI_ERROR (Status)) {\r
     //\r
-    // Get the Device Path Protocol so the environment variables can be updated\r
+    // Remove DevicePath from ConInDev if exists.\r
     //\r
-    Status = gBS->OpenProtocol (\r
-                    ControllerHandle,\r
-                    &gEfiDevicePathProtocolGuid,\r
-                    (VOID **) &DevicePath,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Remove DevicePath from ConInDev\r
-      //\r
-      ConPlatformUpdateDeviceVariable (\r
-        L"ConInDev",\r
-        DevicePath,\r
-        DELETE\r
-        );\r
-    }\r
+    ConPlatformUpdateDeviceVariable (\r
+      L"ConInDev",\r
+      DevicePath,\r
+      Delete\r
+      );\r
   }\r
+\r
   //\r
   // Uninstall the Console Device GUIDs from Controller Handle\r
   //\r
@@ -520,11 +574,11 @@ 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
@@ -557,36 +611,32 @@ ConPlatformTextOutDriverBindingStop (
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
 \r
   //\r
-  // If it is not a hot-plug device, first delete it from the ConOutDev and ErrOutDev variable.\r
+  // Get the Device Path Protocol firstly\r
   //\r
-  if (!IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &DevicePath,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
     //\r
-    // Get the Device Path Protocol so the environment variables can be updated\r
+    // Remove DevicePath from ConOutDev and ErrOutDev if exists.\r
     //\r
-    Status = gBS->OpenProtocol (\r
-                    ControllerHandle,\r
-                    &gEfiDevicePathProtocolGuid,\r
-                    (VOID **) &DevicePath,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Remove DevicePath from ConOutDev, and ErrOutDev\r
-      //\r
-      ConPlatformUpdateDeviceVariable (\r
-        L"ConOutDev",\r
-        DevicePath,\r
-        DELETE\r
-        );\r
-      ConPlatformUpdateDeviceVariable (\r
-        L"ErrOutDev",\r
-        DevicePath,\r
-        DELETE\r
-        );\r
-    }\r
+    ConPlatformUpdateDeviceVariable (\r
+      L"ConOutDev",\r
+      DevicePath,\r
+      Delete\r
+      );\r
+    ConPlatformUpdateDeviceVariable (\r
+      L"ErrOutDev",\r
+      DevicePath,\r
+      Delete\r
+      );\r
   }\r
+\r
   //\r
   // Uninstall the Console Device GUIDs from Controller Handle\r
   //\r
@@ -854,7 +904,7 @@ ConPlatformUpdateDeviceVariable (
   //\r
   VariableDevicePath = ConPlatformGetVariable (VariableName);\r
 \r
-  if (Operation != DELETE) {\r
+  if (Operation != Delete) {\r
     //\r
     // Match specified DevicePath in Console Variable.\r
     // \r
@@ -865,7 +915,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
@@ -929,10 +979,12 @@ ConPlatformUpdateDeviceVariable (
 }\r
 \r
 /**\r
-  Check if the device supports hot-plug.\r
+  Check if the device supports hot-plug through its device path.\r
+\r
+  This function could be updated to check more types of Hot Plug devices.\r
+  Currently, it checks USB and PCCard device.\r
 \r
-  @param  DriverBindingHandle   Protocol instance pointer.\r
-  @param  ControllerHandle      Handle of device to check.\r
+  @param  DevicePath            Pointer to device's device path.\r
 \r
   @retval TRUE                  The devcie is a hot-plug device\r
   @retval FALSE                 The devcie is not a hot-plug device.\r
@@ -940,26 +992,112 @@ ConPlatformUpdateDeviceVariable (
 **/\r
 BOOLEAN\r
 IsHotPlugDevice (\r
-  EFI_HANDLE    DriverBindingHandle,\r
-  EFI_HANDLE    ControllerHandle\r
+  IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_DEVICE_PATH_PROTOCOL     *CheckDevicePath;\r
+\r
+  CheckDevicePath = DevicePath;\r
+  while (!IsDevicePathEnd (CheckDevicePath)) {\r
+    //\r
+    // Check device whether is hot plug device or not throught Device Path\r
+    // \r
+    if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
+        (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
+         DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
+         DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
+      //\r
+      // If Device is USB device\r
+      //\r
+      return TRUE;\r
+    }\r
+    if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
+        (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
+      //\r
+      // If Device is PCCard\r
+      //\r
+      return TRUE;\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_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;\r
+  UINTN                                EntryCount;\r
+  UINTN                                Index;\r
+  EFI_DEVICE_PATH_PROTOCOL             *ChildDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL             *TempDevicePath;\r
 \r
   //\r
-  // HotPlugDeviceGuid indicates ControllerHandle stands for a hot plug device.\r
+  // Check whether it's a GOP device.\r
   //\r
-  Status = gBS->OpenProtocol (\r
-                  ControllerHandle,\r
-                  &gEfiHotPlugDeviceGuid,\r
-                  NULL,\r
-                  DriverBindingHandle,\r
-                  ControllerHandle,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\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
+\r
+  Status = gBS->OpenProtocolInformation (\r
+                  PciHandle,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  &OpenInfoBuffer,\r
+                  &EntryCount\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return FALSE;\r
   }\r
 \r
+  for (Index = 0; Index < EntryCount; Index++) {\r
+    //\r
+    // Query all the children created by the GOP driver\r
+    //\r
+    if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+      Status = gBS->OpenProtocol (\r
+                      OpenInfoBuffer[Index].ControllerHandle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      (VOID **) &ChildDevicePath,\r
+                      NULL,\r
+                      NULL,\r
+                      EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                      );\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Append the device path to ConOutDev and ErrOutDev\r
+        //\r
+        ConPlatformUpdateDeviceVariable (L"ConOutDev", ChildDevicePath, Append);\r
+        ConPlatformUpdateDeviceVariable (L"ErrOutDev", ChildDevicePath, Append);\r
+      }\r
+    }\r
+  }\r
+  FreePool (OpenInfoBuffer);\r
+\r
   return TRUE;\r
 }\r