From f58f3de07ef4531828c108ea099ff637f8c52d1f Mon Sep 17 00:00:00 2001
From: czhang46 <czhang46@6f19259b-4bc3-4df7-8a09-765794883524>
Date: Fri, 17 Aug 2012 07:43:09 +0000
Subject: [PATCH] Fix  the issue that consplitter should not touch ConIn
 variable & do ConIn connection

Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
Reviewed-by  : Hot Tian <hot.tian@intel.com>
Reviewed-by  : Ni, Ruiyu <ruiyu.ni@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13645 6f19259b-4bc3-4df7-8a09-765794883524
---
 MdeModulePkg/Include/Guid/ConnectConInEvent.h |  24 ++
 MdeModulePkg/MdeModulePkg.dec                 |   3 +
 .../Console/ConSplitterDxe/ConSplitter.c      | 291 +++---------------
 .../Console/ConSplitterDxe/ConSplitter.h      |  23 +-
 .../Console/ConSplitterDxe/ConSplitterDxe.inf |   6 +-
 5 files changed, 86 insertions(+), 261 deletions(-)
 create mode 100644 MdeModulePkg/Include/Guid/ConnectConInEvent.h

diff --git a/MdeModulePkg/Include/Guid/ConnectConInEvent.h b/MdeModulePkg/Include/Guid/ConnectConInEvent.h
new file mode 100644
index 0000000000..fb9d52b174
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/ConnectConInEvent.h
@@ -0,0 +1,24 @@
+/** @file
+  GUID is the name of events used with CreateEventEx in order to be notified
+  when the requires ConIn connection.
+
+  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __CONNECT_CONIN_EVENT_GUID_H__
+#define __CONNECT_CONIN_EVENT_GUID_H__
+
+#define CONNECT_CONIN_EVENT_GUID \
+    { 0xdb4e8151, 0x57ed, 0x4bed, { 0x88, 0x33, 0x67, 0x51, 0xb5, 0xd1, 0xa8, 0xd7 }}
+
+extern EFI_GUID gConnectConInEventGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index bb58f794f1..d3d1a299b4 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -250,6 +250,9 @@
   ## Include/Guid/ExitBootServiceFailed.h
   gEventExitBootServicesFailedGuid   = { 0x4f6c5507, 0x232f, 0x4787, { 0xb9, 0x5e, 0x72, 0xf8, 0x62, 0x49, 0xc, 0xb1 } }
 
+  ## Include/Guid/ConnectConInEvent.h
+  gConnectConInEventGuid             = { 0xdb4e8151, 0x57ed, 0x4bed, { 0x88, 0x33, 0x67, 0x51, 0xb5, 0xd1, 0xa8, 0xd7 }}
+
 [Ppis]
   ## Include/Ppi/AtaController.h
   gPeiAtaControllerPpiGuid       = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
index dc23e321c8..d34e7ce5aa 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
@@ -620,6 +620,18 @@ ConSplitterTextInConstructor (
                   ConInPrivate,
                   &ConInPrivate->SimplePointer.WaitForInput
                   );
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Create Event to signal ConIn connection request
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  ConSplitterEmptyCallbackFunction,
+                  NULL,
+                  &gConnectConInEventGuid,
+                  &ConInPrivate->ConnectConIn
+                  );
 
   return Status;
 }
@@ -3310,245 +3322,6 @@ ConSplitterTextInPrivateReadKeyStroke (
   return EFI_NOT_READY;
 }
 
-/**
-  Connect the specific Usb device which match the short form device path,
-  and whose bus is determined by Host Controller.
-
-  @param  DevicePath             A short-form device path that starts with the first
-                                 element being a USB WWID or a USB Class device
-                                 path
-
-  @return EFI_INVALID_PARAMETER  DevicePath is NULL pointer.
-                                 DevicePath is not a USB device path.
-
-  @return EFI_SUCCESS            Success to connect USB device
-  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterConnectUsbShortFormDevicePath (
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
-  )
-{
-  EFI_STATUS                            Status;
-  EFI_HANDLE                            *Handles;
-  UINTN                                 HandleCount;
-  UINTN                                 Index;
-  EFI_PCI_IO_PROTOCOL                   *PciIo;
-  UINT8                                 Class[3];
-  BOOLEAN                               AtLeastOneConnected;
-
-  //
-  // Check the passed in parameters
-  //
-  if (DevicePath == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
-      ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))
-     ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Find the usb host controller firstly, then connect with the remaining device path
-  //
-  AtLeastOneConnected = FALSE;
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEfiPciIoProtocolGuid,
-                  NULL,
-                  &HandleCount,
-                  &Handles
-                  );
-  for (Index = 0; Index < HandleCount; Index++) {
-    Status = gBS->HandleProtocol (
-                    Handles[Index],
-                    &gEfiPciIoProtocolGuid,
-                    (VOID **) &PciIo
-                    );
-    if (!EFI_ERROR (Status)) {
-      //
-      // Check whether the Pci device is the wanted usb host controller
-      //
-      Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
-      if (!EFI_ERROR (Status) &&
-          ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
-         ) {
-        Status = gBS->ConnectController (
-                        Handles[Index],
-                        NULL,
-                        DevicePath,
-                        FALSE
-                        );
-        if (!EFI_ERROR(Status)) {
-          AtLeastOneConnected = TRUE;
-        }
-      }
-    }
-  }
-
-  return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
-}
-
-
-/**
-  This function will create all handles associate with every device
-  path node. If the handle associate with one device path node can not
-  be created successfully, then still give one chance to do the dispatch,
-  which load the missing drivers if possible.
-
-  @param  DevicePathToConnect   The device path which will be connected, it CANNOT be
-                                a multi-instance device path
-  @param  MatchingHandle        Return the controller handle closest to the DevicePathToConnect
-
-  @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
-  @retval EFI_NOT_FOUND         Failed to create all handles associate with every device path node.
-  @retval EFI_SUCCESS           Successful to create all handles associate with every device path node.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterConnectDevicePath (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect,
-  OUT EFI_HANDLE                *MatchingHandle          OPTIONAL
-  )
-{
-  EFI_STATUS                Status;
-  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
-  EFI_HANDLE                Handle;
-  EFI_HANDLE                PreviousHandle;
-
-  if (DevicePathToConnect == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Start the real work of connect with RemainingDevicePath
-  //
-  PreviousHandle = NULL;
-  do {
-    //
-    // Find the handle that best matches the Device Path. If it is only a
-    // partial match the remaining part of the device path is returned in
-    // RemainingDevicePath.
-    //
-    RemainingDevicePath = DevicePathToConnect;
-    Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
-    if (!EFI_ERROR (Status)) {
-      if (Handle == PreviousHandle) {
-        //
-        // If no forward progress is made try invoking the Dispatcher.
-        // A new FV may have been added to the system an new drivers
-        // may now be found.
-        // Status == EFI_SUCCESS means a driver was dispatched
-        // Status == EFI_NOT_FOUND means no new drivers were dispatched
-        //
-        Status = gDS->Dispatch ();
-      }
-
-      if (!EFI_ERROR (Status)) {
-        PreviousHandle = Handle;
-        //
-        // Connect all drivers that apply to Handle and RemainingDevicePath,
-        // the Recursive flag is FALSE so only one level will be expanded.
-        //
-        // Do not check the connect status here, if the connect controller fail,
-        // then still give the chance to do dispatch, because partial
-        // RemainingDevicepath may be in the new FV
-        //
-        // 1. If the connect fail, RemainingDevicepath and handle will not
-        //    change, so next time will do the dispatch, then dispatch's status
-        //    will take effect
-        // 2. If the connect success, the RemainingDevicepath and handle will
-        //    change, then avoid the dispatch, we have chance to continue the
-        //    next connection
-        //
-        gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
-        if (MatchingHandle != NULL) {
-          *MatchingHandle = Handle;
-        }
-      }
-    }
-    //
-    // Loop until RemainingDevicePath is an empty device path
-    //
-  } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
-
-  ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));
-
-  return Status;
-}
-
-
-/**
-  Connect to all ConIn device which is in the ConIn variable.
-
-  @param  DevicePath             A short-form device path that starts with the first
-                                 element being a USB WWID or a USB Class device
-                                 path
-
-  @return EFI_INVALID_PARAMETER  DevicePath is NULL pointer.
-                                 DevicePath is not a USB device path.
-
-  @return EFI_SUCCESS            Success to connect USB device
-  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterConnectConInDevicePath (
-  
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL              *DevicePath;
-  EFI_DEVICE_PATH_PROTOCOL              *DevicePathInst;
-  EFI_DEVICE_PATH_PROTOCOL              *CopyDevicePath;
-  UINTN                                 Size;
-  EFI_DEVICE_PATH_PROTOCOL              *Next;
-
-  DevicePath = GetEfiGlobalVariable (L"ConIn");
-
-  //
-  // Check the passed in parameters
-  //
-  if (DevicePath == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  CopyDevicePath = DevicePath;
-
-  DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);
-  while (DevicePathInst != NULL) {
-
-    Next      = DevicePathInst;
-    while (!IsDevicePathEndType (Next)) {
-      Next = NextDevicePathNode (Next);
-    }
-
-    SetDevicePathEndNode (Next);
-    
-    //
-    // Connect the USB console
-    // USB console device path is a short-form device path that 
-    //  starts with the first element being a USB WWID
-    //  or a USB Class device path
-    //
-    if ((DevicePathType (DevicePathInst) == MESSAGING_DEVICE_PATH) &&
-       ((DevicePathSubType (DevicePathInst) == MSG_USB_CLASS_DP)
-       || (DevicePathSubType (DevicePathInst) == MSG_USB_WWID_DP)
-       )) {
-      ConSplitterConnectUsbShortFormDevicePath (DevicePathInst);
-    } else {
-      ConSplitterConnectDevicePath (DevicePathInst, NULL);
-    }    
-    DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);
-  }
-  return EFI_SUCCESS;
-}
-
 
 
 /**
@@ -3578,11 +3351,11 @@ ConSplitterTextInReadKeyStroke (
   Private->KeyEventSignalState = FALSE;
 
   //
-  // Connect ConIn when first call in Lazy ConIn mode
+  // Signal ConnectConIn event on first call in Lazy ConIn mode
   //
   if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {
     DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));    
-    ConSplitterConnectConInDevicePath ();
+    gBS->SignalEvent (Private->ConnectConIn);
     mConInIsConnect = TRUE;
   }
 
@@ -3758,15 +3531,6 @@ ConSplitterTextInReadKeyStrokeEx (
     return EFI_INVALID_PARAMETER;
   }
 
-  //
-  // Connect ConIn when first call in Lazy ConIn mode
-  //
-  if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {
-    DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));    
-    ConSplitterConnectConInDevicePath ();
-    mConInIsConnect = TRUE;
-  }
-
   Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 
   Private->KeyEventSignalState = FALSE;
@@ -3774,6 +3538,15 @@ ConSplitterTextInReadKeyStrokeEx (
   KeyData->Key.UnicodeChar  = 0;
   KeyData->Key.ScanCode     = SCAN_NULL;
 
+  //
+  // Signal ConnectConIn event on first call in Lazy ConIn mode
+  //
+  if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {
+    DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));    
+    gBS->SignalEvent (Private->ConnectConIn);
+    mConInIsConnect = TRUE;
+  }
+
   //
   // if no physical console input device exists, return EFI_NOT_READY;
   // if any physical console input device has key input,
@@ -4938,3 +4711,21 @@ ConSplitterTextOutEnableCursor (
   return ReturnStatus;
 }
 
+
+/**
+  An empty function to pass error checking of CreateEventEx ().
+
+  @param  Event                 Event whose notification function is being invoked.
+  @param  Context               Pointer to the notification function's context,
+                                which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+ConSplitterEmptyCallbackFunction (
+  IN EFI_EVENT                Event,
+  IN VOID                     *Context
+  )
+{
+  return;
+}
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
index 680e02f812..b5b1435d92 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
@@ -18,8 +18,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Uefi.h>
 #include <PiDxe.h>
 
-#include <IndustryStandard/Pci.h>
-
 #include <Protocol/DevicePath.h>
 #include <Protocol/ComponentName.h>
 #include <Protocol/DriverBinding.h>
@@ -30,11 +28,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SimpleTextInEx.h>
 #include <Protocol/GraphicsOutput.h>
 #include <Protocol/UgaDraw.h>
-#include <Protocol/PciIo.h>
 
 #include <Guid/ConsoleInDevice.h>
 #include <Guid/StandardErrorDevice.h>
 #include <Guid/ConsoleOutDevice.h>
+#include <Guid/ConnectConInEvent.h>
 
 #include <Library/PcdLib.h>
 #include <Library/DebugLib.h>
@@ -45,9 +43,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/DxeServicesTableLib.h>
-
 
 //
 // Driver Binding Externs
@@ -150,6 +145,7 @@ typedef struct {
 
   BOOLEAN                            KeyEventSignalState;
   BOOLEAN                            InputEventSignalState;
+  EFI_EVENT                          ConnectConIn;
 } TEXT_IN_SPLITTER_PRIVATE_DATA;
 
 #define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS(a)  \
@@ -1989,5 +1985,20 @@ TextOutSetMode (
   IN  UINTN                           ModeNumber
   );
 
+/**
+  An empty function to pass error checking of CreateEventEx ().
+
+  @param  Event                 Event whose notification function is being invoked.
+  @param  Context               Pointer to the notification function's context,
+                                which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+ConSplitterEmptyCallbackFunction (
+  IN EFI_EVENT                Event,
+  IN VOID                     *Context
+  );
+
 
 #endif
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
index 3d2b5bc318..4885dc7fe9 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
@@ -68,15 +68,12 @@
   UefiDriverEntryPoint
   DebugLib
   PcdLib
-  DevicePathLib
-  DxeServicesLib
-  DxeServicesTableLib
 
 [Guids]
   gEfiConsoleInDeviceGuid                       ## SOMETIMES_CONSUMES
   gEfiStandardErrorDeviceGuid                   ## SOMETIMES_CONSUMES
   gEfiConsoleOutDeviceGuid                      ## SOMETIMES_CONSUMES
-
+  gConnectConInEventGuid                        ## ALWAYS_CONSUMES
 
 [Protocols]
   gEfiSimplePointerProtocolGuid                 ## BY_START
@@ -86,7 +83,6 @@
   gEfiSimpleTextOutProtocolGuid                 ## BY_START
   gEfiGraphicsOutputProtocolGuid                ## BY_START
   gEfiUgaDrawProtocolGuid                       ## BY_START
-  gEfiPciIoProtocolGuid                         ## PROTOCOL CONSUMES
 
 
 [FeaturePcd]