summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/MdeModulePkg.dec7
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c264
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h6
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf8
4 files changed, 282 insertions, 3 deletions
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index ec2bdaa69d..ed0d94c683 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -633,7 +633,7 @@
# boundary as close to the top of memory as feasible.
#
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxEfiSystemTablePointerAddress|0x0|UINT64|0x30001027
-
+
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## This PCD defines the Console output column and the default value is 25 according to UEFI spec.
# This PCD could be set to 0 then console output could be at max column and max row.
@@ -814,6 +814,11 @@
# the extension FPDT boot records got after ReadyToBoot and before ExitBootService.
gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize|0x0|UINT32|0x0001005F
+ ## This PCD specifies whether ConIn device are connected on demand. If TRUE, ConIn
+ # device are not connected during BDS and ReadKeyStroke/ReadKeyStrokeEx produced
+ # by Consplitter should be called before any real key read operation.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|FALSE|BOOLEAN|0x10000060
+
## This PCD specified whether the S.M.A.R.T feature of attached ATA hard disks are enabled.
gEfiMdeModulePkgTokenSpaceGuid.PcdAtaSmartEnable|TRUE|BOOLEAN|0x00010065
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
index c1edd5dccf..cc73729b97 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
@@ -30,6 +30,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ConSplitter.h"
//
+// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode.
+// default not connect
+//
+BOOLEAN mConInIsConnect = FALSE;
+
+//
// Text In Splitter Private Data template
//
GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = {
@@ -3304,6 +3310,246 @@ 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;
+}
+
+
/**
Reads the next keystroke from the input device. The WaitForKey Event can
@@ -3331,6 +3577,15 @@ ConSplitterTextInReadKeyStroke (
Private->KeyEventSignalState = FALSE;
+ //
+ // 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;
+ }
+
return ConSplitterTextInPrivateReadKeyStroke (Private, Key);
}
@@ -3503,6 +3758,15 @@ 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;
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
index 22c9e19c74..680e02f812 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
@@ -16,6 +16,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define _CON_SPLITTER_H_
#include <Uefi.h>
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
#include <Protocol/DevicePath.h>
#include <Protocol/ComponentName.h>
@@ -27,6 +30,7 @@ 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>
@@ -41,6 +45,8 @@ 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>
//
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
index a0e4b62eb2..3d2b5bc318 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
@@ -10,7 +10,7 @@
# Note: If only UGA Draw protocol is installed in system table, PcdUgaConsumeSupport
# should be set to TRUE.
#
-# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 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
@@ -68,6 +68,9 @@
UefiDriverEntryPoint
DebugLib
PcdLib
+ DevicePathLib
+ DxeServicesLib
+ DxeServicesTableLib
[Guids]
gEfiConsoleInDeviceGuid ## SOMETIMES_CONSUMES
@@ -83,6 +86,7 @@
gEfiSimpleTextOutProtocolGuid ## BY_START
gEfiGraphicsOutputProtocolGuid ## BY_START
gEfiUgaDrawProtocolGuid ## BY_START
+ gEfiPciIoProtocolGuid ## PROTOCOL CONSUMES
[FeaturePcd]
@@ -93,4 +97,4 @@
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn
-
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand