From 838a9c58c949a47194f507561eb44f9b1b7499ac Mon Sep 17 00:00:00 2001 From: czhang46 Date: Mon, 30 Jul 2012 06:04:13 +0000 Subject: [PATCH] Add 2 new Bds features 1. Lazy ConIn 2. OsIndicationsSupported & OsIndications Signed-off-by: Chao Zhang Reviewed-by: Hot Tian git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13567 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/MdeModulePkg.dec | 7 +- .../Console/ConSplitterDxe/ConSplitter.c | 264 ++++++++++++++++++ .../Console/ConSplitterDxe/ConSplitter.h | 6 + .../Console/ConSplitterDxe/ConSplitterDxe.inf | 8 +- 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 @@ -29,6 +29,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 // @@ -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 +#include + +#include #include #include @@ -27,6 +30,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include @@ -41,6 +45,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include +#include // 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.
+# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
# # 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 -- 2.39.2