diff options
author | czhang46 <czhang46@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-07-30 06:04:13 +0000 |
---|---|---|
committer | czhang46 <czhang46@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-07-30 06:04:13 +0000 |
commit | 838a9c58c949a47194f507561eb44f9b1b7499ac (patch) | |
tree | 83214f9f3d75508cd65b2e87ad1dfbc16638841e /MdeModulePkg/Universal/Console | |
parent | 18cf3950226cb7e279f19978ea441ce6639f7bb3 (diff) | |
download | edk2-platforms-838a9c58c949a47194f507561eb44f9b1b7499ac.tar.xz |
Add 2 new Bds features
1. Lazy ConIn
2. OsIndicationsSupported & OsIndications
Signed-off-by: Chao Zhang<chao.b.zhang@intel.com>
Reviewed-by: Hot Tian<Hot.Tian@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13567 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/Console')
3 files changed, 276 insertions, 2 deletions
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
|