]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add 2 new Bds features
authorczhang46 <czhang46@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 30 Jul 2012 06:04:13 +0000 (06:04 +0000)
committerczhang46 <czhang46@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 30 Jul 2012 06:04:13 +0000 (06:04 +0000)
  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

MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf

index ec2bdaa69d224837c9fdd3de75d373841685a112..ed0d94c683e1d352ec07732705b6c93a174e9cb4 100644 (file)
   #  boundary as close to the top of memory as feasible.\r
   #\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxEfiSystemTablePointerAddress|0x0|UINT64|0x30001027\r
-  \r
+\r
 [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]\r
   ## This PCD defines the Console output column and the default value is 25 according to UEFI spec.\r
   #  This PCD could be set to 0 then console output could be at max column and max row.\r
   #  the extension FPDT boot records got after ReadyToBoot and before ExitBootService.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize|0x0|UINT32|0x0001005F\r
 \r
+  ## This PCD specifies whether ConIn device are connected on demand. If TRUE, ConIn\r
+  #  device are not connected during BDS and ReadKeyStroke/ReadKeyStrokeEx produced\r
+  #  by Consplitter should be called before any real key read operation.\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|FALSE|BOOLEAN|0x10000060\r
+\r
   ## This PCD specified whether the S.M.A.R.T feature of attached ATA hard disks are enabled.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAtaSmartEnable|TRUE|BOOLEAN|0x00010065\r
 \r
index c1edd5dccf4bed91629dbcef7a12dbd6bb9ce2a4..cc73729b97009824c09694511acb02eed4183a4c 100644 (file)
@@ -29,6 +29,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "ConSplitter.h"\r
 \r
+//\r
+// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode. \r
+// default not connect\r
+//\r
+BOOLEAN  mConInIsConnect = FALSE;\r
+\r
 //\r
 // Text In Splitter Private Data template\r
 //\r
@@ -3304,6 +3310,246 @@ ConSplitterTextInPrivateReadKeyStroke (
   return EFI_NOT_READY;\r
 }\r
 \r
+/*\r
+  Connect the specific Usb device which match the short form device path,\r
+  and whose bus is determined by Host Controller.\r
+\r
+  @param  DevicePath             A short-form device path that starts with the first\r
+                                 element being a USB WWID or a USB Class device\r
+                                 path\r
+\r
+  @return EFI_INVALID_PARAMETER  DevicePath is NULL pointer.\r
+                                 DevicePath is not a USB device path.\r
+\r
+  @return EFI_SUCCESS            Success to connect USB device\r
+  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterConnectUsbShortFormDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_HANDLE                            *Handles;\r
+  UINTN                                 HandleCount;\r
+  UINTN                                 Index;\r
+  EFI_PCI_IO_PROTOCOL                   *PciIo;\r
+  UINT8                                 Class[3];\r
+  BOOLEAN                               AtLeastOneConnected;\r
+\r
+  //\r
+  // Check the passed in parameters\r
+  //\r
+  if (DevicePath == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||\r
+      ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))\r
+     ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Find the usb host controller firstly, then connect with the remaining device path\r
+  //\r
+  AtLeastOneConnected = FALSE;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &Handles\r
+                  );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->HandleProtocol (\r
+                    Handles[Index],\r
+                    &gEfiPciIoProtocolGuid,\r
+                    (VOID **) &PciIo\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Check whether the Pci device is the wanted usb host controller\r
+      //\r
+      Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
+      if (!EFI_ERROR (Status) &&\r
+          ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))\r
+         ) {\r
+        Status = gBS->ConnectController (\r
+                        Handles[Index],\r
+                        NULL,\r
+                        DevicePath,\r
+                        FALSE\r
+                        );\r
+        if (!EFI_ERROR(Status)) {\r
+          AtLeastOneConnected = TRUE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  This function will create all handles associate with every device\r
+  path node. If the handle associate with one device path node can not\r
+  be created successfully, then still give one chance to do the dispatch,\r
+  which load the missing drivers if possible.\r
+\r
+  @param  DevicePathToConnect   The device path which will be connected, it CANNOT be\r
+                                a multi-instance device path\r
+  @param  MatchingHandle        Return the controller handle closest to the DevicePathToConnect\r
+\r
+  @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.\r
+  @retval EFI_NOT_FOUND         Failed to create all handles associate with every device path node.\r
+  @retval EFI_SUCCESS           Successful to create all handles associate with every device path node.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterConnectDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect,\r
+  OUT EFI_HANDLE                *MatchingHandle          OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;\r
+  EFI_HANDLE                Handle;\r
+  EFI_HANDLE                PreviousHandle;\r
+\r
+  if (DevicePathToConnect == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Start the real work of connect with RemainingDevicePath\r
+  //\r
+  PreviousHandle = NULL;\r
+  do {\r
+    //\r
+    // Find the handle that best matches the Device Path. If it is only a\r
+    // partial match the remaining part of the device path is returned in\r
+    // RemainingDevicePath.\r
+    //\r
+    RemainingDevicePath = DevicePathToConnect;\r
+    Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Handle == PreviousHandle) {\r
+        //\r
+        // If no forward progress is made try invoking the Dispatcher.\r
+        // A new FV may have been added to the system an new drivers\r
+        // may now be found.\r
+        // Status == EFI_SUCCESS means a driver was dispatched\r
+        // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
+        //\r
+        Status = gDS->Dispatch ();\r
+      }\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        PreviousHandle = Handle;\r
+        //\r
+        // Connect all drivers that apply to Handle and RemainingDevicePath,\r
+        // the Recursive flag is FALSE so only one level will be expanded.\r
+        //\r
+        // Do not check the connect status here, if the connect controller fail,\r
+        // then still give the chance to do dispatch, because partial\r
+        // RemainingDevicepath may be in the new FV\r
+        //\r
+        // 1. If the connect fail, RemainingDevicepath and handle will not\r
+        //    change, so next time will do the dispatch, then dispatch's status\r
+        //    will take effect\r
+        // 2. If the connect success, the RemainingDevicepath and handle will\r
+        //    change, then avoid the dispatch, we have chance to continue the\r
+        //    next connection\r
+        //\r
+        gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
+        if (MatchingHandle != NULL) {\r
+          *MatchingHandle = Handle;\r
+        }\r
+      }\r
+    }\r
+    //\r
+    // Loop until RemainingDevicePath is an empty device path\r
+    //\r
+  } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
+\r
+  ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Connect to all ConIn device which is in the ConIn variable.\r
+\r
+  @param  DevicePath             A short-form device path that starts with the first\r
+                                 element being a USB WWID or a USB Class device\r
+                                 path\r
+\r
+  @return EFI_INVALID_PARAMETER  DevicePath is NULL pointer.\r
+                                 DevicePath is not a USB device path.\r
+\r
+  @return EFI_SUCCESS            Success to connect USB device\r
+  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterConnectConInDevicePath (\r
+  \r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL              *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL              *DevicePathInst;\r
+  EFI_DEVICE_PATH_PROTOCOL              *CopyDevicePath;\r
+  UINTN                                 Size;\r
+  EFI_DEVICE_PATH_PROTOCOL              *Next;\r
+\r
+  DevicePath = GetEfiGlobalVariable (L"ConIn");\r
+\r
+  //\r
+  // Check the passed in parameters\r
+  //\r
+  if (DevicePath == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  CopyDevicePath = DevicePath;\r
+\r
+  DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
+  while (DevicePathInst != NULL) {\r
+\r
+    Next      = DevicePathInst;\r
+    while (!IsDevicePathEndType (Next)) {\r
+      Next = NextDevicePathNode (Next);\r
+    }\r
+\r
+    SetDevicePathEndNode (Next);\r
+    \r
+    //\r
+    // Connect the USB console\r
+    // USB console device path is a short-form device path that \r
+    //  starts with the first element being a USB WWID\r
+    //  or a USB Class device path\r
+    //\r
+    if ((DevicePathType (DevicePathInst) == MESSAGING_DEVICE_PATH) &&\r
+       ((DevicePathSubType (DevicePathInst) == MSG_USB_CLASS_DP)\r
+       || (DevicePathSubType (DevicePathInst) == MSG_USB_WWID_DP)\r
+       )) {\r
+      ConSplitterConnectUsbShortFormDevicePath (DevicePathInst);\r
+    } else {\r
+      ConSplitterConnectDevicePath (DevicePathInst, NULL);\r
+    }    \r
+    DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
 \r
 /**\r
   Reads the next keystroke from the input device. The WaitForKey Event can\r
@@ -3331,6 +3577,15 @@ ConSplitterTextInReadKeyStroke (
 \r
   Private->KeyEventSignalState = FALSE;\r
 \r
+  //\r
+  // Connect ConIn when first call in Lazy ConIn mode\r
+  //\r
+  if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {\r
+    DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));    \r
+    ConSplitterConnectConInDevicePath ();\r
+    mConInIsConnect = TRUE;\r
+  }\r
+\r
   return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
 }\r
 \r
@@ -3503,6 +3758,15 @@ ConSplitterTextInReadKeyStrokeEx (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // Connect ConIn when first call in Lazy ConIn mode\r
+  //\r
+  if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {\r
+    DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));    \r
+    ConSplitterConnectConInDevicePath ();\r
+    mConInIsConnect = TRUE;\r
+  }\r
+\r
   Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
 \r
   Private->KeyEventSignalState = FALSE;\r
index 22c9e19c74ae40250effa69bd2cdc4636fbf4e41..680e02f8120da7521b9530bee5745ad783ef2ccc 100644 (file)
@@ -16,6 +16,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define _CON_SPLITTER_H_\r
 \r
 #include <Uefi.h>\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
 \r
 #include <Protocol/DevicePath.h>\r
 #include <Protocol/ComponentName.h>\r
@@ -27,6 +30,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SimpleTextInEx.h>\r
 #include <Protocol/GraphicsOutput.h>\r
 #include <Protocol/UgaDraw.h>\r
+#include <Protocol/PciIo.h>\r
 \r
 #include <Guid/ConsoleInDevice.h>\r
 #include <Guid/StandardErrorDevice.h>\r
@@ -41,6 +45,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
 \r
 \r
 //\r
index a0e4b62eb2ea1659b49aec19981d7e1a53070712..3d2b5bc3186cccd0491ed6f7752ae26c37c5cf8d 100644 (file)
@@ -10,7 +10,7 @@
 # Note: If only UGA Draw protocol is installed in system table, PcdUgaConsumeSupport\r
 # should be set to TRUE.\r
 #\r
-# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -68,6 +68,9 @@
   UefiDriverEntryPoint\r
   DebugLib\r
   PcdLib\r
+  DevicePathLib\r
+  DxeServicesLib\r
+  DxeServicesTableLib\r
 \r
 [Guids]\r
   gEfiConsoleInDeviceGuid                       ## SOMETIMES_CONSUMES\r
@@ -83,6 +86,7 @@
   gEfiSimpleTextOutProtocolGuid                 ## BY_START\r
   gEfiGraphicsOutputProtocolGuid                ## BY_START\r
   gEfiUgaDrawProtocolGuid                       ## BY_START\r
+  gEfiPciIoProtocolGuid                         ## PROTOCOL CONSUMES\r
 \r
 \r
 [FeaturePcd]\r
@@ -93,4 +97,4 @@
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn\r
-\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand\r